Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion apps/website/qa/queen-runners-contract.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
cabinetOf,
callRunners,
runnerOf,
RUNNER_SCRIPT_URL,
setupLines,
} from '../src/lib/queenRunners.ts'

Expand Down Expand Up @@ -146,7 +147,24 @@ const env = (fetch, token = 'session-token') => ({ base: BASE, fetch, token: ()
{
const lines = setupLines(TOKEN, 'https://queen.invalid').join('\n')
assert.ok(lines.includes(TOKEN))
assert.ok(!/API_KEY|sk-|provider/i.test(lines))
// A provider KEY, in any spelling. Not the bare word: the production branch
// the script is downloaded from is named fix/queen-worker-provider-and-...
const providerKey = /API_KEY|\bsk-|provider[_ -]?key/i
assert.ok(!providerKey.test(lines))
// ...and the narrower pattern still catches what it is for.
for (const leak of ['export ANTHROPIC_API_KEY=x', 'sk-abc', 'PROVIDER_KEY=x', 'your provider key']) {
assert.ok(providerKey.test(leak), leak)
}
// ...and they run the runner, which pushes to the person's own public fork.
assert.ok(lines.includes('TRIOS_RUNNER_REMOTE=https://github.com/'))
assert.ok(lines.includes('node queen-runner.mjs'))
// The production branch, the one the deployed Queen is built from.
assert.ok(
RUNNER_SCRIPT_URL.startsWith(
'https://raw.githubusercontent.com/gHashTag/BrowserOS/fix/queen-worker-provider-and-prompt-size/',
),
)
assert.ok(RUNNER_SCRIPT_URL.endsWith('/queen-runner.mjs'))
assert.ok(CABINET_HOME.startsWith('https://app.t27.ai/queen/'))
}

Expand Down
4 changes: 2 additions & 2 deletions apps/website/src/components/GetStartedBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const COPY: Record<'en' | 'ru', { eyebrow: string; title: string; lede: string;
cta: 'Create a runner',
href: CABINET_HOME,
external: true,
note: `${RUNNERS_COPY.en.nextStage} Renting a GPU or an FPGA out for TRI is planned: there is no GPU worker and no job format yet.`,
note: `${RUNNERS_COPY.en.howItWorks} Renting a GPU or an FPGA out for TRI is planned: there is no GPU worker and no job format yet.`,
more: [
{ label: 'How to join the swarm', href: '#/blog/how-to-join-the-swarm' },
{ label: 'The FPGA flow, timed layer by layer', href: '#/devkit' },
Expand Down Expand Up @@ -94,7 +94,7 @@ const COPY: Record<'en' | 'ru', { eyebrow: string; title: string; lede: string;
cta: 'Создать раннер',
href: CABINET_HOME,
external: true,
note: `${RUNNERS_COPY.ru.nextStage} Сдавать GPU или FPGA в аренду за TRI — в планах: GPU-воркера и формата задач пока нет.`,
note: `${RUNNERS_COPY.ru.howItWorks} Сдавать GPU или FPGA в аренду за TRI — в планах: GPU-воркера и формата задач пока нет.`,
more: [
{ label: 'Как войти в рой', href: '#/blog/how-to-join-the-swarm' },
{ label: 'FPGA-поток, по слоям и по времени', href: '#/devkit' },
Expand Down
10 changes: 9 additions & 1 deletion apps/website/src/components/QueenRunners.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
callRunners,
type RunnersCall,
type RunnersEnv,
RUNNER_README_URL,
setupLines,
} from '../lib/queenRunners'
import { RUNNERS_COPY } from '../lib/queenRunnersCopy'
Expand Down Expand Up @@ -184,7 +185,14 @@ export default function QueenRunners({ lang }: { lang: 'en' | 'ru' }) {
</p>
</>
)}
{view?.state !== 'pending' && <p className="qr-small">{c.nextStage}</p>}
{view?.state !== 'pending' && (
<p className="qr-small">
{c.howItWorks}{' '}
<a href={RUNNER_README_URL} target="_blank" rel="noreferrer">
{c.readme}
</a>
</p>
)}
</section>
)
}
20 changes: 16 additions & 4 deletions apps/website/src/lib/queenRunners.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,14 +157,26 @@ export async function callRunners(env: RunnersEnv, call: RunnersCall, previous?:
}

/**
* The lines a person pastes on their own machine. The provider key is named as
* an environment variable THEY set there and is never part of anything this
* page writes, stores or sends.
* The branch the Queen's production service is built from, so the script a
* person downloads is the one the server they connect to speaks.
*/
export const RUNNER_BRANCH = 'fix/queen-worker-provider-and-prompt-size'

/** The runner script and its instructions, in the Queen's own repository. */
export const RUNNER_SCRIPT_URL = `https://raw.githubusercontent.com/gHashTag/BrowserOS/${RUNNER_BRANCH}/trios/agent-server/tools/queen-runner/queen-runner.mjs`
export const RUNNER_README_URL = `https://github.com/gHashTag/BrowserOS/blob/${RUNNER_BRANCH}/trios/agent-server/tools/queen-runner/README.md`

/**
* The lines a person pastes on their own machine. The provider key is never
* part of anything this page writes, stores or sends: the runner's agent uses
* whatever key the person already has set up there.
*/
export function setupLines(token: string, base: string): string[] {
return [
`export TRIOS_QUEEN_URL=${base}`,
`export TRIOS_RUNNER_TOKEN=${token}`,
`curl -fsS -X POST -H "Authorization: Bearer $TRIOS_RUNNER_TOKEN" "$TRIOS_QUEEN_URL/queen/runner/heartbeat"`,
'export TRIOS_RUNNER_REMOTE=https://github.com/<you>/<your-public-fork>.git',
`curl -fsSLO ${RUNNER_SCRIPT_URL}`,
'node queen-runner.mjs',
]
}
14 changes: 9 additions & 5 deletions apps/website/src/lib/queenRunnersCopy.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// MY RUNNERS, in words: what a runner is and how far it goes today. The cabinet
// (components/QueenRunners.tsx) draws it, and the homepage's GET STARTED quotes
// its lead and its next stage rather than describing runners a second time, so
// the day taking tasks ships, one edit here moves both.
// its lead and how a runner works rather than describing runners a second
// time, so one edit here moves both.
export interface RunnersCopy {
title: string
lead: string
Expand All @@ -26,7 +26,9 @@ export interface RunnersCopy {
copy: string
copied: string
done: string
nextStage: string
/** What a runner does with a task; the homepage's GET STARTED quotes it. */
howItWorks: string
readme: string
}

export const RUNNERS_COPY: Record<'en' | 'ru', RunnersCopy> = {
Expand All @@ -53,7 +55,8 @@ export const RUNNERS_COPY: Record<'en' | 'ru', RunnersCopy> = {
copy: 'Copy',
copied: 'Copied',
done: 'I saved it',
nextStage: 'Today a runner can connect and show up online. Taking tasks and handing work back is the next stage of the Queen; until it ships there is nothing to take.',
howItWorks: 'The runner takes one task at a time, runs your own coding agent on it (Claude Code by default) and pushes the result to your public fork. The Queen fetches that branch and her review judges it like any other bee’s work. Ctrl-C hands the task back.',
readme: 'Setup and settings',
},
ru: {
title: 'МОИ РАННЕРЫ',
Expand All @@ -78,6 +81,7 @@ export const RUNNERS_COPY: Record<'en' | 'ru', RunnersCopy> = {
copy: 'Скопировать',
copied: 'Скопировано',
done: 'Сохранено',
nextStage: 'Сейчас раннер может подключиться и отображаться «на связи». Выдача задач и приём работы — следующий этап Королевы; пока его нет, брать нечего.',
howItWorks: 'Раннер берёт по одной задаче, запускает на ней ваш собственный агент (по умолчанию Claude Code) и пушит результат в ваш публичный форк. Королева забирает эту ветку, и её ревью оценивает работу так же, как работу любой другой пчелы. Ctrl-C возвращает задачу.',
readme: 'Установка и настройки',
},
}
Loading