Merge pull request 'feature/0.12.0' (#120) from feature/0.12.0 into main
Reviewed-on: #120
42
build.sh
|
|
@ -1083,6 +1083,41 @@ install_zot_agent() {
|
|||
# Stage an on-image NVIDIA pkg repo (all branches) so clawdie_live_gpu can
|
||||
# `pkg install` the detected branch at boot (NVIDIA_UNIVERSAL lane).
|
||||
#
|
||||
# FreeBSD-build-host step (authored on Linux; runs + must be validated on
|
||||
# FreeBSD). Verify on the build host: (1) the `pkg fetch -o` layout matches what
|
||||
# `pkg repo` expects, (2) the dependency closure is complete for offline boot
|
||||
# Build the Astro docs site and stage it as static HTML on the ISO.
|
||||
# When ISO_VERSION is set, the docs carry a version badge matching the image.
|
||||
# Skips silently if node/npm are unavailable.
|
||||
build_and_stage_docs() {
|
||||
local _docs_src="${SCRIPT_DIR}/docs/website"
|
||||
local _docs_out="${MOUNT_POINT}/usr/local/share/clawdie-iso/docs"
|
||||
|
||||
if [ ! -d "${_docs_src}" ]; then
|
||||
echo " Docs source not found at ${_docs_src} — skipping"
|
||||
return 0
|
||||
fi
|
||||
if ! command -v node >/dev/null 2>&1 || ! command -v npm >/dev/null 2>&1; then
|
||||
echo " Node/npm not available — skipping docs build"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo " Building docs (ISO ${ISO_VERSION})..."
|
||||
(
|
||||
cd "${_docs_src}"
|
||||
npm ci --silent 2>&1 || { echo " WARN: npm ci failed, skipping docs"; exit 0; }
|
||||
ASTRO_ISO_VERSION="${ISO_VERSION}" \
|
||||
ASTRO_SITE_URL="file:///usr/local/share/clawdie-iso/docs" \
|
||||
npm run build --silent 2>&1 || { echo " WARN: astro build failed, skipping docs"; exit 0; }
|
||||
)
|
||||
|
||||
if [ -d "${_docs_src}/dist" ]; then
|
||||
mkdir -p "${_docs_out}"
|
||||
cp -a "${_docs_src}/dist/." "${_docs_out}/"
|
||||
echo " Docs staged at /usr/local/share/clawdie-iso/docs/ (version ${ISO_VERSION})"
|
||||
fi
|
||||
}
|
||||
|
||||
# FreeBSD-build-host step (authored on Linux; runs + must be validated on
|
||||
# FreeBSD). Verify on the build host: (1) the `pkg fetch -o` layout matches what
|
||||
# `pkg repo` expects, (2) the dependency closure is complete for offline boot
|
||||
|
|
@ -1288,6 +1323,9 @@ branch, commit, modified state, ISO version, and build channel at image build ti
|
|||
clawdie-ai (TypeScript) is no longer included — it is being phased out in favor
|
||||
of the colibri (Rust) control plane. The `clawdie` name is retained as the brand
|
||||
and bare-metal installer identity.
|
||||
|
||||
hermes-bsd (Python) is the agent CLI and gateway — powers the Telegram bot,
|
||||
agent-to-agent relay, and the operator's primary chat interface.
|
||||
EOF
|
||||
seed_live_ai_source_repo "${SCRIPT_DIR}" "clawdie-iso"
|
||||
seed_live_ai_source_repo "${_resolved_colibri_repo}" "colibri"
|
||||
|
|
@ -1295,6 +1333,9 @@ EOF
|
|||
# just Colibri (Rust). Skipped automatically if the zot checkout is absent.
|
||||
resolve_zot_paths
|
||||
seed_live_ai_source_repo "${_resolved_zot_repo}" "zot"
|
||||
# Hermes Agent source — the agent CLI + gateway for Telegram bot and
|
||||
# agent-to-agent relay. Skipped silently if the checkout is absent.
|
||||
seed_live_ai_source_repo "${HERMES_REPO:-/home/clawdie/ai/hermes-bsd}" "hermes-bsd"
|
||||
chroot "${MOUNT_POINT}" chown -R clawdie:clawdie /home/clawdie/ai
|
||||
}
|
||||
|
||||
|
|
@ -2477,6 +2518,7 @@ configure_live_operator_session
|
|||
install_colibri_service
|
||||
install_zot_agent
|
||||
install_nvidia_universal_repo
|
||||
build_and_stage_docs
|
||||
|
||||
# Copy payload
|
||||
# Rebuild payload paths from scratch inside the reusable work image. A failed
|
||||
|
|
|
|||
28
docs/website/astro.config.mjs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import { defineConfig, passthroughImageService } from 'astro/config';
|
||||
import sitemap from '@astrojs/sitemap';
|
||||
|
||||
const site = process.env.ASTRO_SITE_URL || 'https://clawdie.si';
|
||||
const outDir = process.env.ASTRO_OUT_DIR || './dist';
|
||||
|
||||
export default defineConfig({
|
||||
site,
|
||||
outDir,
|
||||
output: 'static',
|
||||
trailingSlash: 'always',
|
||||
image: {
|
||||
service: passthroughImageService(),
|
||||
},
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en', 'sl'],
|
||||
routing: { prefixDefaultLocale: true, redirectToDefaultLocale: false },
|
||||
},
|
||||
integrations: [
|
||||
sitemap({
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: { en: 'en', sl: 'sl' },
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
6581
docs/website/package-lock.json
generated
Normal file
23
docs/website/package.json
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "clawdie-si",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "astro dev --host 0.0.0.0",
|
||||
"start": "astro dev --host 0.0.0.0",
|
||||
"build": "astro build",
|
||||
"predeploy": "npm run build",
|
||||
"deploy": "node scripts/deploy.mjs",
|
||||
"preview": "astro preview --host 0.0.0.0",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/sitemap": "^3.2.1",
|
||||
"astro": "^5.16.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/check": "^0.9.6",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
5
docs/website/public/clawdie-mark.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="Clawdie mark">
|
||||
<rect width="64" height="64" rx="14" fill="#0d1117"/>
|
||||
<path d="M32 11 53 50H11L32 11Z" fill="none" stroke="#00b4d8" stroke-width="3" stroke-linejoin="round"/>
|
||||
<path d="M21.5 30.5 L42.5 30.5 L32 50 Z" fill="none" stroke="#00b4d8" stroke-width="3" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 383 B |
22
docs/website/scripts/deploy.mjs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
|
||||
const localRoot = process.cwd();
|
||||
const distDir = path.join(localRoot, 'dist');
|
||||
const webroot = process.env.CMS_WEBROOT || '/usr/local/www/clawdie-si';
|
||||
|
||||
if (!fs.existsSync(distDir)) {
|
||||
console.error(`Build output not found: ${distDir}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const result = spawnSync(
|
||||
'rsync',
|
||||
['-av', '--delete', `${distDir}/`, `${webroot}/`],
|
||||
{ stdio: 'inherit', env: process.env },
|
||||
);
|
||||
|
||||
if (result.status !== 0) {
|
||||
process.exit(result.status ?? 1);
|
||||
}
|
||||
83
docs/website/src/components/LandingBody.astro
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
---
|
||||
import { getCollection, render } from 'astro:content';
|
||||
import type { Locale } from '../i18n';
|
||||
import { t } from '../i18n';
|
||||
|
||||
interface Props {
|
||||
locale: Locale;
|
||||
}
|
||||
|
||||
const { locale } = Astro.props;
|
||||
const strings = t(locale);
|
||||
|
||||
const all = await getCollection('landing', ({ id }) => id.startsWith(`${locale}/`));
|
||||
const bySection = Object.fromEntries(all.map((e) => [e.data.section, e]));
|
||||
|
||||
const heroEntry = bySection['hero'];
|
||||
const aboutEntry = bySection['about'];
|
||||
const archEntry = bySection['architecture'];
|
||||
const ctaEntry = bySection['install-cta'];
|
||||
|
||||
const Hero = heroEntry ? (await render(heroEntry)).Content : null;
|
||||
const About = aboutEntry ? (await render(aboutEntry)).Content : null;
|
||||
const Arch = archEntry ? (await render(archEntry)).Content : null;
|
||||
const Cta = ctaEntry ? (await render(ctaEntry)).Content : null;
|
||||
|
||||
// Only set during ISO builds — shows the exact image version.
|
||||
const isoVersion = import.meta.env.ASTRO_ISO_VERSION || null;
|
||||
const isoTagUrl = isoVersion
|
||||
? `https://code.smilepowered.org/clawdie/clawdie-iso/releases/tag/v${isoVersion}`
|
||||
: null;
|
||||
---
|
||||
|
||||
<header class="hero">
|
||||
<div class="header-inner">
|
||||
<div class="brand-mark"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64" role="img" aria-label="Clawdie"><path d="M32 11 53 50H11L32 11Z" fill="none" stroke="currentColor" stroke-width="3" stroke-linejoin="round"/><path d="M21.5 30.5 L42.5 30.5 L32 50 Z" fill="none" stroke="currentColor" stroke-width="3" stroke-linejoin="round"/></svg></div>
|
||||
<div class="header-text">
|
||||
<h1>Clawdie<br /><span>{locale === 'sl' ? 'AI v vaših rokah' : 'AI you own'}</span></h1>
|
||||
<p class="tagline">{strings.meta.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="hero-statement">
|
||||
{Hero && <Hero />}
|
||||
</div>
|
||||
|
||||
{
|
||||
About && (
|
||||
<section class="landing-section" id="about">
|
||||
<h2>{aboutEntry?.data.title}</h2>
|
||||
<About />
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
Arch && (
|
||||
<section class="landing-section" id="architecture">
|
||||
<h2>{archEntry?.data.title}</h2>
|
||||
<Arch />
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
Cta && (
|
||||
<section class="landing-section" id="install">
|
||||
<h2>{ctaEntry?.data.title}</h2>
|
||||
<Cta />
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
isoVersion && (
|
||||
<footer class="iso-version-badge">
|
||||
<p>
|
||||
Clawdie ISO {isoVersion} —{' '}
|
||||
<a href={isoTagUrl}>release notes</a>
|
||||
</p>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
34
docs/website/src/components/LangSwitcher.astro
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
import type { Locale } from '../i18n';
|
||||
import { locales, t } from '../i18n';
|
||||
|
||||
interface Props {
|
||||
current: Locale;
|
||||
}
|
||||
|
||||
const { current } = Astro.props;
|
||||
|
||||
const pathname = Astro.url.pathname;
|
||||
const prefix = `/${current}`;
|
||||
const rest = pathname.startsWith(prefix)
|
||||
? pathname.slice(prefix.length) || '/'
|
||||
: pathname;
|
||||
|
||||
const labelFor: Record<Locale, string> = {
|
||||
en: 'EN',
|
||||
sl: 'SI',
|
||||
};
|
||||
---
|
||||
|
||||
<nav class="lang-switch" aria-label={t(current).switcher.label}>
|
||||
{
|
||||
locales.map((loc) => {
|
||||
const href = `/${loc}${rest.startsWith('/') ? rest : `/${rest}`}`;
|
||||
return (
|
||||
<a href={href} class={loc === current ? 'active' : ''} lang={loc} hreflang={loc}>
|
||||
{labelFor[loc]}
|
||||
</a>
|
||||
);
|
||||
})
|
||||
}
|
||||
</nav>
|
||||
31
docs/website/src/components/OperatorBanner.astro
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
import type { Locale } from '../i18n';
|
||||
import { t } from '../i18n';
|
||||
|
||||
interface Props {
|
||||
locale: Locale;
|
||||
}
|
||||
|
||||
const { locale } = Astro.props;
|
||||
const s = t(locale).banner;
|
||||
---
|
||||
|
||||
<div id="operator-banner" class="operator-banner" hidden>
|
||||
<div class="operator-banner-text">
|
||||
<strong>{s.heading}</strong> {s.body}
|
||||
</div>
|
||||
<div class="operator-banner-actions">
|
||||
<a href="/controlplane/">{s.openControlplane}</a>
|
||||
<a href="https://docs.clawdie.si/">{s.readDocs}</a>
|
||||
<a href="https://docs.clawdie.si/operate/public-domain/">{s.claimDomain}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script is:inline>
|
||||
(function () {
|
||||
if (typeof window === 'undefined') return;
|
||||
if (window.location.hostname === 'clawdie.si') return;
|
||||
var el = document.getElementById('operator-banner');
|
||||
if (el) el.hidden = false;
|
||||
})();
|
||||
</script>
|
||||
13
docs/website/src/content.config.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import { defineCollection, z } from 'astro:content';
|
||||
import { glob } from 'astro/loaders';
|
||||
|
||||
const landing = defineCollection({
|
||||
loader: glob({ base: './src/content/landing', pattern: '**/*.md' }),
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
order: z.number(),
|
||||
section: z.enum(['hero', 'about', 'architecture', 'install-cta']),
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = { landing };
|
||||
16
docs/website/src/content/landing/en/about.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
title: What is Clawdie
|
||||
order: 2
|
||||
section: about
|
||||
---
|
||||
|
||||
Clawdie is a **self-hosted AI control plane** for operators who refuse to rent
|
||||
their compute, their data, or their users' privacy.
|
||||
|
||||
You install it on your own hardware — a workstation, a colocated box, a basement
|
||||
server. It provisions FreeBSD jails, runs your models, and gives every tenant on
|
||||
your machine a clean slice of the platform: their own database, their own site,
|
||||
their own backups.
|
||||
|
||||
No telemetry leaks upstream. No model weights walk out the door. No vendor
|
||||
decides what your assistant is allowed to say tomorrow.
|
||||
16
docs/website/src/content/landing/en/architecture.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
title: Architecture
|
||||
order: 3
|
||||
section: architecture
|
||||
---
|
||||
|
||||
A Clawdie install has three layers:
|
||||
|
||||
- **Host** — FreeBSD with ZFS, nginx, Postgres, jail manager.
|
||||
- **Control plane** — the operator's command surface; provisions tenants, runs
|
||||
the assistant, ships the publish report.
|
||||
- **Tenants** — isolated jails, each with its own site, database, and backup
|
||||
policy. Tenants don't see each other; the operator sees everything.
|
||||
|
||||
Everything is reproducible. The same `setup` command that builds your machine
|
||||
today will build the same machine on a fresh box tomorrow.
|
||||
9
docs/website/src/content/landing/en/hero.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
title: Hero
|
||||
order: 1
|
||||
section: hero
|
||||
---
|
||||
|
||||
**Sovereign AI is an engineering problem, not a regulatory one.**
|
||||
The hardware exists. The models exist. The know-how exists.
|
||||
**The only thing missing is the decision to install it yourself.**
|
||||
12
docs/website/src/content/landing/en/install-cta.md
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
title: Install
|
||||
order: 4
|
||||
section: install-cta
|
||||
---
|
||||
|
||||
Boot the ISO, answer four questions, walk away.
|
||||
By the time you come back, your machine is provisioned, your assistant is
|
||||
online, and your first tenant site is reachable.
|
||||
|
||||
Read the [installation guide](https://docs.clawdie.si/install/) or jump
|
||||
straight to the [ISO download](https://docs.clawdie.si/install/iso/).
|
||||
10
docs/website/src/content/landing/sl/about.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
title: Kaj je Clawdie
|
||||
order: 2
|
||||
section: about
|
||||
---
|
||||
|
||||
Clawdie je **samogosotvana AI nadzorna ravan** za operaterje, ki nočejo najemati
|
||||
svoje računske moči, svojih podatkov ali zasebnosti svojih uporabnikov.
|
||||
|
||||
<!-- TODO: full SL translation pending Crowdin wiring -->
|
||||
9
docs/website/src/content/landing/sl/architecture.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
title: Arhitektura
|
||||
order: 3
|
||||
section: architecture
|
||||
---
|
||||
|
||||
Namestitev Clawdie ima tri plasti: gostitelj, nadzorna ravan, najemniki.
|
||||
|
||||
<!-- TODO: full SL translation pending Crowdin wiring -->
|
||||
11
docs/website/src/content/landing/sl/hero.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
title: Hero
|
||||
order: 1
|
||||
section: hero
|
||||
---
|
||||
|
||||
**Suverena AI je inženirski problem, ne regulativni.**
|
||||
Strojna oprema obstaja. Modeli obstajajo. Znanje obstaja.
|
||||
**Edino, kar manjka, je odločitev, da to namestite sami.**
|
||||
|
||||
<!-- TODO: full SL translation pending Crowdin wiring -->
|
||||
11
docs/website/src/content/landing/sl/install-cta.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
title: Namestitev
|
||||
order: 4
|
||||
section: install-cta
|
||||
---
|
||||
|
||||
Zaženite ISO, odgovorite na štiri vprašanja, odidite.
|
||||
|
||||
Preberite [vodič za namestitev](https://docs.clawdie.si/install/).
|
||||
|
||||
<!-- TODO: full SL translation pending Crowdin wiring -->
|
||||
32
docs/website/src/i18n/en.ts
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import type { Strings } from './types';
|
||||
|
||||
export const en: Strings = {
|
||||
meta: {
|
||||
title: 'Clawdie — Sovereign AI infrastructure',
|
||||
description:
|
||||
'Self-hosted AI control plane: your data, your jails, your rules. Operator-owned infrastructure that ships ready-to-use.',
|
||||
},
|
||||
nav: {
|
||||
docs: 'Docs',
|
||||
controlplane: 'Control plane',
|
||||
source: 'Source',
|
||||
},
|
||||
switcher: {
|
||||
label: 'Language',
|
||||
en: 'EN',
|
||||
sl: 'SL',
|
||||
},
|
||||
banner: {
|
||||
heading: 'You are not on clawdie.si.',
|
||||
body: 'This page is being served from an operator install. Use the controls below.',
|
||||
openControlplane: 'Open control plane',
|
||||
readDocs: 'Read docs',
|
||||
claimDomain: 'Claim a public domain',
|
||||
},
|
||||
footer: {
|
||||
tagline: 'Operator-owned AI · No surveillance, no rent extraction',
|
||||
docsLink: 'docs.clawdie.si',
|
||||
sourceLink: 'codeberg.org/Clawdie/Clawdie-AI',
|
||||
rights: 'Released under AGPL-3.0',
|
||||
},
|
||||
};
|
||||
14
docs/website/src/i18n/index.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { en } from './en';
|
||||
import { sl } from './sl';
|
||||
import type { Locale, Strings } from './types';
|
||||
|
||||
export const locales: Locale[] = ['en', 'sl'];
|
||||
export const defaultLocale: Locale = 'en';
|
||||
|
||||
const registry: Record<Locale, Strings> = { en, sl };
|
||||
|
||||
export function t(locale: Locale): Strings {
|
||||
return registry[locale];
|
||||
}
|
||||
|
||||
export type { Locale, Strings };
|
||||
32
docs/website/src/i18n/sl.ts
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import type { Strings } from './types';
|
||||
|
||||
export const sl: Strings = {
|
||||
meta: {
|
||||
title: 'Clawdie — Suverena AI infrastruktura',
|
||||
description:
|
||||
'Samogosotvana AI nadzorna ravan: vaši podatki, vaši jaili, vaša pravila. Operaterjeva infrastruktura, ki je takoj uporabna.',
|
||||
},
|
||||
nav: {
|
||||
docs: 'Dokumentacija',
|
||||
controlplane: 'Nadzorna ravan',
|
||||
source: 'Izvorna koda',
|
||||
},
|
||||
switcher: {
|
||||
label: 'Jezik',
|
||||
en: 'EN',
|
||||
sl: 'SL',
|
||||
},
|
||||
banner: {
|
||||
heading: 'Niste na clawdie.si.',
|
||||
body: 'Ta stran se streže iz operaterjeve namestitve. Uporabite spodnje gumbe.',
|
||||
openControlplane: 'Odpri nadzorno ravan',
|
||||
readDocs: 'Preberi dokumentacijo',
|
||||
claimDomain: 'Prevzemi javno domeno',
|
||||
},
|
||||
footer: {
|
||||
tagline: 'AI v lasti operaterja · Brez nadzora, brez najemnine',
|
||||
docsLink: 'docs.clawdie.si',
|
||||
sourceLink: 'codeberg.org/Clawdie/Clawdie-AI',
|
||||
rights: 'Izdano pod AGPL-3.0',
|
||||
},
|
||||
};
|
||||
31
docs/website/src/i18n/types.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
export type Locale = 'en' | 'sl';
|
||||
|
||||
export interface Strings {
|
||||
meta: {
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
||||
nav: {
|
||||
docs: string;
|
||||
controlplane: string;
|
||||
source: string;
|
||||
};
|
||||
switcher: {
|
||||
label: string;
|
||||
en: string;
|
||||
sl: string;
|
||||
};
|
||||
banner: {
|
||||
heading: string;
|
||||
body: string;
|
||||
openControlplane: string;
|
||||
readDocs: string;
|
||||
claimDomain: string;
|
||||
};
|
||||
footer: {
|
||||
tagline: string;
|
||||
docsLink: string;
|
||||
sourceLink: string;
|
||||
rights: string;
|
||||
};
|
||||
}
|
||||
68
docs/website/src/layouts/Landing.astro
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
import '../styles/global.css';
|
||||
import LangSwitcher from '../components/LangSwitcher.astro';
|
||||
import type { Locale } from '../i18n';
|
||||
import { locales, t } from '../i18n';
|
||||
|
||||
interface Props {
|
||||
locale: Locale;
|
||||
}
|
||||
|
||||
const { locale } = Astro.props;
|
||||
const strings = t(locale);
|
||||
const site = Astro.site?.toString().replace(/\/$/, '') ?? 'https://clawdie.si';
|
||||
const path = Astro.url.pathname;
|
||||
const stripPrefix = (p: string, l: Locale) => {
|
||||
const pref = `/${l}`;
|
||||
return p.startsWith(pref) ? p.slice(pref.length) || '/' : p;
|
||||
};
|
||||
const sharedPath = stripPrefix(path, locale);
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang={locale}>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>{strings.meta.title}</title>
|
||||
<meta name="description" content={strings.meta.description} />
|
||||
{
|
||||
locales.map((l) => (
|
||||
<link
|
||||
rel="alternate"
|
||||
hreflang={l}
|
||||
href={`${site}/${l}${sharedPath === '/' ? '/' : sharedPath}`}
|
||||
/>
|
||||
))
|
||||
}
|
||||
<link
|
||||
rel="alternate"
|
||||
hreflang="x-default"
|
||||
href={`${site}/en${sharedPath === '/' ? '/' : sharedPath}`}
|
||||
/>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,600;1,300;1,400&family=DM+Mono:wght@300;400&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="triangle-bg"></div>
|
||||
<div class="container">
|
||||
<LangSwitcher current={locale} />
|
||||
<slot />
|
||||
<footer class="site-footer">
|
||||
<div>
|
||||
{strings.footer.tagline}<br />
|
||||
<a href="https://docs.clawdie.si/">{strings.footer.docsLink}</a>
|
||||
·
|
||||
<a href="https://codeberg.org/Clawdie/Clawdie-AI">{strings.footer.sourceLink}</a>
|
||||
<br />
|
||||
{strings.footer.rights}
|
||||
</div>
|
||||
<div class="footer-mark"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="32" height="32"><path d="M32 11 53 50H11L32 11Z" fill="none" stroke="currentColor" stroke-width="3" stroke-linejoin="round"/><path d="M21.5 30.5 L42.5 30.5 L32 50 Z" fill="none" stroke="currentColor" stroke-width="3" stroke-linejoin="round"/></svg></div>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
8
docs/website/src/pages/en/index.astro
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
import Landing from '../../layouts/Landing.astro';
|
||||
import LandingBody from '../../components/LandingBody.astro';
|
||||
---
|
||||
|
||||
<Landing locale="en">
|
||||
<LandingBody locale="en" />
|
||||
</Landing>
|
||||
8
docs/website/src/pages/sl/index.astro
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
import Landing from '../../layouts/Landing.astro';
|
||||
import LandingBody from '../../components/LandingBody.astro';
|
||||
---
|
||||
|
||||
<Landing locale="sl">
|
||||
<LandingBody locale="sl" />
|
||||
</Landing>
|
||||
355
docs/website/src/styles/global.css
Normal file
|
|
@ -0,0 +1,355 @@
|
|||
:root {
|
||||
--bg: #0d1117;
|
||||
--accent: #00b4d8;
|
||||
--accent-dark: #0096b7;
|
||||
--fg: #e2e8f0;
|
||||
--fg-dim: #c9d1d9;
|
||||
--grey: #8b949e;
|
||||
--rule: #21262d;
|
||||
--paper: #161b22;
|
||||
--paper-2: #1c2333;
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--bg);
|
||||
color: var(--fg-dim);
|
||||
font-family: 'Cormorant Garamond', Georgia, serif;
|
||||
font-size: 22px;
|
||||
line-height: 1.7;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.triangle-bg {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
opacity: 0.06;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100'%3E%3Cg stroke='%2300b4d8' stroke-width='0.8' fill='none'%3E%3Cline x1='0' y1='25' x2='40' y2='25'/%3E%3Cline x1='60' y1='25' x2='100' y2='25'/%3E%3Cline x1='0' y1='75' x2='40' y2='75'/%3E%3Cline x1='60' y1='75' x2='100' y2='75'/%3E%3Cline x1='25' y1='0' x2='25' y2='40'/%3E%3Cline x1='25' y1='60' x2='25' y2='100'/%3E%3Cline x1='75' y1='0' x2='75' y2='40'/%3E%3Cline x1='75' y1='60' x2='75' y2='100'/%3E%3Cpath d='M40 25 L50 25 L50 40'/%3E%3Cpath d='M60 25 L50 25 L50 40'/%3E%3Cpath d='M40 75 L50 75 L50 60'/%3E%3Cpath d='M60 75 L50 75 L50 60'/%3E%3C/g%3E%3Cg fill='%2300b4d8'%3E%3Ccircle cx='25' cy='25' r='2.5'/%3E%3Ccircle cx='75' cy='25' r='2.5'/%3E%3Ccircle cx='25' cy='75' r='2.5'/%3E%3Ccircle cx='75' cy='75' r='2.5'/%3E%3Ccircle cx='50' cy='50' r='2.5'/%3E%3C/g%3E%3C/svg%3E");
|
||||
background-size: 100px 100px;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
padding: 0 2rem;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.top-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 1.5rem;
|
||||
padding: 1.2rem 0;
|
||||
border-bottom: 1px solid var(--rule);
|
||||
font-family: 'DM Mono', monospace;
|
||||
font-size: 0.85rem;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.top-nav a {
|
||||
color: var(--grey);
|
||||
text-decoration: none;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.top-nav a:hover,
|
||||
.top-nav a.active {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
header.hero {
|
||||
padding: 5rem 0 3rem;
|
||||
position: relative;
|
||||
animation: fadeUp 1.2s ease forwards;
|
||||
}
|
||||
|
||||
.header-inner {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 3rem;
|
||||
}
|
||||
|
||||
.brand-mark {
|
||||
font-size: 5rem;
|
||||
line-height: 1;
|
||||
animation: float 6s ease-in-out infinite;
|
||||
flex-shrink: 0;
|
||||
color: var(--accent);
|
||||
font-family: 'DM Mono', monospace;
|
||||
}
|
||||
|
||||
.header-text h1 {
|
||||
font-size: clamp(3rem, 8vw, 5.5rem);
|
||||
font-weight: 300;
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 0.95;
|
||||
color: var(--fg);
|
||||
}
|
||||
|
||||
.header-text h1 span {
|
||||
color: var(--accent);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.tagline {
|
||||
font-family: 'DM Mono', monospace;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0.15em;
|
||||
text-transform: uppercase;
|
||||
color: var(--grey);
|
||||
margin-top: 1.2rem;
|
||||
border-left: 2px solid var(--accent);
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
.hero-statement {
|
||||
background: var(--paper-2);
|
||||
color: var(--fg);
|
||||
padding: 4rem 3rem;
|
||||
margin: 3rem 0;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero-statement::before {
|
||||
content: '△';
|
||||
position: absolute;
|
||||
right: -1rem;
|
||||
top: -2rem;
|
||||
font-size: 12rem;
|
||||
color: var(--accent);
|
||||
opacity: 0.08;
|
||||
font-family: 'DM Mono', monospace;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.hero-statement p {
|
||||
font-size: clamp(1.4rem, 3vw, 2rem);
|
||||
font-weight: 300;
|
||||
line-height: 1.5;
|
||||
color: var(--fg);
|
||||
}
|
||||
|
||||
.hero-statement strong {
|
||||
color: var(--accent);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
section.landing-section {
|
||||
margin: 4rem 0;
|
||||
}
|
||||
|
||||
section.landing-section h2 {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 300;
|
||||
font-style: italic;
|
||||
color: var(--fg);
|
||||
margin-bottom: 1.2rem;
|
||||
position: relative;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
section.landing-section h2::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 40px;
|
||||
height: 1px;
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
section.landing-section p {
|
||||
color: var(--fg-dim);
|
||||
font-size: 1.1em;
|
||||
margin-bottom: 1rem;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
section.landing-section a {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid transparent;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
|
||||
section.landing-section a:hover {
|
||||
border-bottom-color: var(--accent);
|
||||
}
|
||||
|
||||
footer.site-footer {
|
||||
margin-top: 6rem;
|
||||
padding: 3rem 0;
|
||||
border-top: 1px solid var(--rule);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
font-family: 'DM Mono', monospace;
|
||||
font-size: 0.85rem;
|
||||
letter-spacing: 0.1em;
|
||||
color: var(--grey);
|
||||
text-transform: uppercase;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
footer.site-footer a {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid transparent;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
|
||||
footer.site-footer a:hover {
|
||||
border-bottom-color: var(--accent);
|
||||
}
|
||||
|
||||
.footer-mark {
|
||||
font-size: 2rem;
|
||||
opacity: 0.3;
|
||||
color: var(--accent);
|
||||
animation: float 8s ease-in-out infinite reverse;
|
||||
}
|
||||
|
||||
/* --- LANG SWITCHER (OSA-style) --- */
|
||||
.lang-switch {
|
||||
position: absolute;
|
||||
top: 1.5rem;
|
||||
right: 2rem;
|
||||
display: flex;
|
||||
gap: 0.3rem;
|
||||
font-family: 'DM Mono', monospace;
|
||||
font-size: 0.8rem;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.lang-switch a {
|
||||
color: var(--grey);
|
||||
text-decoration: none;
|
||||
padding: 0.25rem 0.55rem;
|
||||
border: 1px solid var(--rule);
|
||||
transition:
|
||||
color 0.2s,
|
||||
border-color 0.2s;
|
||||
}
|
||||
|
||||
.lang-switch a.active,
|
||||
.lang-switch a:hover {
|
||||
color: var(--accent);
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
/* --- OPERATOR BANNER --- */
|
||||
.operator-banner {
|
||||
background: var(--paper);
|
||||
border-bottom: 1px solid var(--accent);
|
||||
padding: 1rem 2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1.5rem;
|
||||
flex-wrap: wrap;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.operator-banner-text {
|
||||
font-family: 'DM Mono', monospace;
|
||||
font-size: 0.78rem;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--fg-dim);
|
||||
}
|
||||
|
||||
.operator-banner-text strong {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.operator-banner-actions {
|
||||
display: flex;
|
||||
gap: 0.6rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.operator-banner-actions a {
|
||||
font-family: 'DM Mono', monospace;
|
||||
font-size: 0.72rem;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
color: var(--fg);
|
||||
text-decoration: none;
|
||||
border: 1px solid var(--accent);
|
||||
padding: 0.45rem 0.9rem;
|
||||
transition:
|
||||
background 0.2s,
|
||||
color 0.2s;
|
||||
}
|
||||
|
||||
.operator-banner-actions a:hover {
|
||||
background: var(--accent);
|
||||
color: var(--bg);
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%,
|
||||
100% {
|
||||
transform: translateY(0px) rotate(-5deg);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-12px) rotate(3deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.header-inner {
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
.brand-mark {
|
||||
font-size: 3.5rem;
|
||||
}
|
||||
.header-text h1 {
|
||||
font-size: 3rem;
|
||||
}
|
||||
.hero-statement {
|
||||
padding: 2.5rem 1.5rem;
|
||||
}
|
||||
footer.site-footer {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
.lang-switch {
|
||||
right: 1rem;
|
||||
top: 1rem;
|
||||
}
|
||||
}
|
||||
5
docs/website/tsconfig.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"include": [".astro/types.d.ts", "**/*"],
|
||||
"exclude": ["dist"]
|
||||
}
|
||||
|
|
@ -60,6 +60,11 @@ agent's keys were loaded before the daemon started, so Colibri auto-spawns
|
|||
the agent on boot. Check with:
|
||||
colibri status
|
||||
|
||||
If a mother-mcp key was seeded, git pull from Forgejo works out-of-the-box:
|
||||
cd ~/ai/clawdie-iso && git pull
|
||||
cd ~/ai/clawdie-ai && git pull
|
||||
The key is wired via ~/.ssh/config for both mother MCP and code.smilepowered.org.
|
||||
|
||||
Readable operator guide:
|
||||
/usr/local/share/clawdie-iso/seed/README.txt
|
||||
|
||||
|
|
|
|||
|
|
@ -94,12 +94,17 @@ Inside it, any of these are honored:
|
|||
/<agent>/ssh/<name>.pub OUTBOUND: installed to ~/.ssh/<name>.pub (0644).
|
||||
|
||||
/<agent>/ssh/config OUTBOUND: installed to ~/.ssh/config (0600).
|
||||
Typical use — a host alias for the mother server:
|
||||
Typical use — host entries for the dual-purpose
|
||||
mother-mcp key (see next section):
|
||||
|
||||
Host mother
|
||||
HostName osa.smilepowered.org
|
||||
User clawdie
|
||||
IdentityFile ~/.ssh/osa-mother-2026
|
||||
User colibri
|
||||
IdentityFile ~/.ssh/mother-mcp
|
||||
|
||||
Host code.smilepowered.org
|
||||
IdentityFile ~/.ssh/mother-mcp
|
||||
IdentitiesOnly yes
|
||||
|
||||
/<agent>/ssh/known_hosts OUTBOUND: merged into ~/.ssh/known_hosts (0644),
|
||||
de-duplicated. Pin the mother server's host key
|
||||
|
|
@ -107,6 +112,30 @@ Inside it, any of these are honored:
|
|||
not stop on an unknown-host prompt. Get the line
|
||||
with: ssh-keyscan osa.smilepowered.org
|
||||
|
||||
/<agent>/ssh/mother-mcp DUAL-PURPOSE OUTBOUND KEY. This private key
|
||||
serves two roles with a single identity:
|
||||
|
||||
1. MCP calls to mother via colibri-mcp.
|
||||
The mother server's authorized_keys entry
|
||||
forces command="colibri-mcp",restrict —
|
||||
this key can ONLY invoke the MCP tool,
|
||||
never a shell session.
|
||||
|
||||
2. Git pull from Forgejo (code.smilepowered.org).
|
||||
Add this same key as a read-only deploy key
|
||||
in the Forgejo repository settings (repo →
|
||||
Settings → Deploy Keys → Add Deploy Key,
|
||||
with "Enable write access" OFF). Read-only
|
||||
is sufficient for `git pull` and limits
|
||||
blast radius if the key is ever compromised.
|
||||
|
||||
Placing a key named mother-mcp here gives the
|
||||
agent git pull from Forgejo out-of-the-box with
|
||||
no additional configuration — the accompanying
|
||||
ssh/config Host entries route it for both
|
||||
destinations. No other key is needed for either
|
||||
purpose.
|
||||
|
||||
Agent directory names may contain only A-Z a-z 0-9 . _ - (no spaces or
|
||||
slashes). The name `ssh` is reserved for Layer 1.
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.6 KiB |
|
|
@ -1,17 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">
|
||||
<!-- Clawdie Start-button icon: upward triangle, brand navy->blue gradient
|
||||
fill with a coral edge. Matches the clawdie.si triangle wordmark and the
|
||||
operator wallpaper palette. Source of truth; PNG renders are derived. -->
|
||||
<defs>
|
||||
<linearGradient id="tri" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#21457a"/>
|
||||
<stop offset="100%" stop-color="#0f3460"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<!-- Clawdie Start-button icon: unified geodesic 2V logo.
|
||||
Outer triangle + inverted inner triangle whose vertices
|
||||
touch the midpoints of the outer sides.
|
||||
Cyan on transparent — inherits panel background. -->
|
||||
<path d="M32 7 L57 55 L7 55 Z"
|
||||
fill="url(#tri)"
|
||||
stroke="#e94560"
|
||||
stroke-width="3.5"
|
||||
fill="none"
|
||||
stroke="#00b4d8"
|
||||
stroke-width="3"
|
||||
stroke-linejoin="round"/>
|
||||
<path d="M19.5 31 L44.5 31 L32 55 Z"
|
||||
fill="none"
|
||||
stroke="#00b4d8"
|
||||
stroke-width="3"
|
||||
stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 707 B After Width: | Height: | Size: 642 B |
BIN
live/operator-session/wallpapers/clawdie-6v-dome-bg-v2.png
Normal file
|
After Width: | Height: | Size: 5 MiB |
BIN
live/operator-session/wallpapers/clawdie-6v-dome-bg.png
Normal file
|
After Width: | Height: | Size: 5.3 MiB |
|
Before Width: | Height: | Size: 164 KiB After Width: | Height: | Size: 176 KiB |
|
|
@ -1,28 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="2560" height="1440" viewBox="0 0 2560 1440">
|
||||
<!-- Clawdie operator USB wallpaper: brand navy->blue diagonal gradient with a
|
||||
subtle centered triangle motif and wordmark. Same palette as clawdie.si
|
||||
(#1a1a2e / #16213e / #0f3460 / #e94560). Source of truth; PNG is derived. -->
|
||||
<!-- Clawdie operator USB wallpaper: dark diagonal gradient with a
|
||||
centered geodesic 2V triangle motif and wordmark.
|
||||
Unified logo — outer triangle + inverted inner triangle at midpoints. -->
|
||||
<defs>
|
||||
<linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" stop-color="#1a1a2e"/>
|
||||
<stop offset="50%" stop-color="#16213e"/>
|
||||
<stop offset="100%" stop-color="#0f3460"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="tri" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#21457a"/>
|
||||
<stop offset="100%" stop-color="#0f3460"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="2560" height="1440" fill="url(#bg)"/>
|
||||
<path d="M1280 400 L1620 1010 L940 1010 Z"
|
||||
fill="url(#tri)"
|
||||
stroke="#e94560"
|
||||
stroke-width="7"
|
||||
<!-- Geodesic 2V logo — outer triangle -->
|
||||
<path d="M1280 340 L1680 1060 L880 1060 Z"
|
||||
fill="none"
|
||||
stroke="#00b4d8"
|
||||
stroke-width="6"
|
||||
stroke-linejoin="round"
|
||||
opacity="0.22"/>
|
||||
opacity="0.35"/>
|
||||
<!-- Geodesic 2V logo — inverted inner triangle at midpoints -->
|
||||
<path d="M1080 700 L1480 700 L1280 1060 Z"
|
||||
fill="none"
|
||||
stroke="#00b4d8"
|
||||
stroke-width="6"
|
||||
stroke-linejoin="round"
|
||||
opacity="0.35"/>
|
||||
<text x="1280" y="1180" text-anchor="middle" font-family="sans-serif"
|
||||
font-size="120" font-weight="bold" fill="#e94560" opacity="0.18">Clawdie</text>
|
||||
font-size="120" font-weight="bold" fill="#00b4d8" opacity="0.18">Clawdie</text>
|
||||
<text x="1280" y="1260" text-anchor="middle" font-family="sans-serif"
|
||||
font-size="42" fill="#ffffff" opacity="0.10">AI you own</text>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.4 KiB |
|
|
@ -113,10 +113,17 @@ cat > "${ETC_DIR}/provider.env" <<'EOF'
|
|||
VAULT_SERVER="https://vault.smilepowered.org"
|
||||
BW_SERVER="https://vault.smilepowered.org"
|
||||
|
||||
# Auto-spawn one Pi agent on daemon startup once a DeepSeek key is present
|
||||
# Auto-spawn one zot agent on daemon startup once a DeepSeek key is present
|
||||
# (the Operator Image OOTB flow). The daemon sources this file, so the spawned
|
||||
# Pi inherits the provider keys set here.
|
||||
COLIBRI_AUTOSPAWN_PI="YES"
|
||||
# agent inherits the provider keys set here.
|
||||
COLIBRI_AUTOSPAWN="YES"
|
||||
# zot is the default harness — pi is available but zot has richer provider
|
||||
# support (DeepSeek native, OpenRouter, ~25 providers) and a built-in
|
||||
# Telegram bot mode. Set COLIBRI_AUTOSPAWN_BINARY=pi to switch back.
|
||||
COLIBRI_AUTOSPAWN_BINARY="zot"
|
||||
# Telegram bot token — set this to enable the bot channel (@your_bot).
|
||||
# Leave blank to use CLI/TUI/Dashboard channels only.
|
||||
# TELEGRAM_BOT_TOKEN=""
|
||||
EOF
|
||||
chmod 0600 "${ETC_DIR}/provider.env" 2>/dev/null || true
|
||||
|
||||
|
|
@ -155,16 +162,14 @@ BW_SERVER="https://vault.smilepowered.org"
|
|||
# DEEPSEEK_ENDPOINT="https://api.deepseek.com/chat/completions"
|
||||
# DEEPSEEK_MODEL="deepseek-v4-pro"
|
||||
#
|
||||
# Telegram bot (optional):
|
||||
# TELEGRAM_BOT_TOKEN="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
|
||||
#
|
||||
# Behavior toggles (non-secret):
|
||||
# COLIBRI_AUTOSPAWN_PI="YES" # auto-spawn one Pi on daemon startup
|
||||
# COLIBRI_PI_BINARY="pi" # Pi executable name/path; zot is staged on
|
||||
# # the image but needs the zot-rpc driver
|
||||
# # before it can autospawn (spawner uses
|
||||
# # stdin(Stdio::null()) — zot needs stdin).
|
||||
# # See: ADR-agent-harness-consolidation.md
|
||||
# # + colibri#143 (zot-rpc-driver).
|
||||
# COLIBRI_AUTOSPAWN_PI_ARGS="--mode json" # Pi argv
|
||||
# COLIBRI_MCP_EXTERNAL_CALL="1" # allow Pi (via colibri-mcp) to call
|
||||
# COLIBRI_AUTOSPAWN="YES" # auto-spawn one agent on daemon startup
|
||||
# COLIBRI_AUTOSPAWN_BINARY="zot" # agent harness: zot (default) | pi
|
||||
# COLIBRI_AUTOSPAWN_ARGS="--mode json" # agent argv
|
||||
# COLIBRI_MCP_EXTERNAL_CALL="1" # allow agent (via colibri-mcp) to call
|
||||
# # external MCP servers; set by
|
||||
# # clawdie-enable-mother
|
||||
EOF
|
||||
|
|
|
|||