@hybridlabor-api/aos 4.4.2-beta.8 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.de.md +10 -10
- package/README.md +10 -10
- package/README.pt.md +10 -10
- package/installer.js +210 -17
- package/package.json +1 -1
- package/skills/global_config/openwiki-skill/scripts/install_daemon.ps1 +81 -28
- package/skills/global_config/openwiki-skill/scripts/install_daemon.sh +78 -25
- package/lib/internal-addon-oauth.js +0 -276
package/README.de.md
CHANGED
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
[](https://www.npmjs.com/package/@hybridlabor-api/aos)
|
|
21
21
|
[](https://github.com/hybridlabor-api/aos)
|
|
22
22
|
[](LICENSE)
|
|
23
|
-
[](https://github.com/hybridlabor-api/aos)
|
|
24
24
|
[](https://github.com/NVIDIA/SkillSpector)
|
|
25
25
|
|
|
26
|
-
> **Supercharging von KI-Coding-Agenten mit
|
|
26
|
+
> **Supercharging von KI-Coding-Agenten mit 184 hochkuratierten Skills, 19 lokalen MCP Wrappern und tiefgreifenden Integrationen für die Creative-Technology-Branche.**
|
|
27
27
|
|
|
28
28
|
Willkommen im **BDB DEV Skills & MCP Configuration** Repository. Dieses Projekt dient als Rückgrat unseres Entwicklungs-Ecosystems für Creative & Full-Stack Development. Es erweitert KI-Agenten um hochspezialisierte Fähigkeiten, die speziell auf die Event- und Medientechnologie-Branche sowie auf allgemeine Software-Entwicklung zugeschnitten sind.
|
|
29
29
|
|
|
@@ -80,11 +80,11 @@ Keines dieser Plugins ist in diesem Paket enthalten — es handelt sich um unabh
|
|
|
80
80
|
|
|
81
81
|
## Übersicht
|
|
82
82
|
|
|
83
|
-
Dieses Repo liefert drei Dinge: eine kuratierte Skill-Bibliothek für Coding-Agenten, einen Installer, der diese (plus
|
|
83
|
+
Dieses Repo liefert drei Dinge: eine kuratierte Skill-Bibliothek für Coding-Agenten, einen Installer, der diese (plus 19 lokale MCP Wrapper) in das von Ihnen genutzte Harness einbindet, und einen Dispatcher-Graphen, der sie als Multi-Agenten Build-Pipeline orchestriert. Siehe [AOS: Der Dispatcher-Graph](#-aos-der-dispatcher-graph) weiter unten für Details zur Funktionsweise der Pipeline selbst.
|
|
84
84
|
|
|
85
|
-
## 🌟
|
|
85
|
+
## 🌟 184 Optimierte Skills
|
|
86
86
|
|
|
87
|
-
Wir haben mit einem gewaltigen Pool von über 1.400 rohen KI-Skills begonnen. Nach intensiven Tests, Filterungen und Verfeinerungen haben wir sie zu einem hochkuratierten Set von **
|
|
87
|
+
Wir haben mit einem gewaltigen Pool von über 1.400 rohen KI-Skills begonnen. Nach intensiven Tests, Filterungen und Verfeinerungen haben wir sie zu einem hochkuratierten Set von **184 Optimierten Skills** destilliert (mit nativer OpenWiki-Dokumentationsengine, dem **lokalen semantischen Gedächtnis memB** und jetzt der **Universal Agent Harness Synchronisation in v4.0.0**).
|
|
88
88
|
|
|
89
89
|
Diese Skills sind präzise optimiert, damit Agenten keine Zeit mit redundanten Aufgaben verschwenden, sondern mit maximaler Autonomie, strengen Architekturvorgaben und robustem Kontextbewusstsein agieren.
|
|
90
90
|
|
|
@@ -93,8 +93,8 @@ Anstatt Agenten durch generische Anweisungen irren zu lassen, setzt die oberste
|
|
|
93
93
|
- **`godmode-engineering`**: Erzwingt Domain-Driven Design, strenge TypeScript-Prüfungen, Clean Architecture und systematisches Debugging.
|
|
94
94
|
- **`godmode-ui-ux`**: Der Frontend-Goldstandard. Erzwingt BDB "Anti-Slop"-Prinzipien, Barrierefreiheit (Accessibility) und fluide Bewegungsdynamiken.
|
|
95
95
|
- **`godmode-shipping`**: Der finale Wächter für Production Releases. Erzwingt Spec-Driven Development, Pre-Launch-Prüfungen und sichere Rollbacks.
|
|
96
|
-
- **`godmode-eventtech`**: Das oberste Regelwerk für die BDB Creator Engine, das 3D, Medien und
|
|
97
|
-
- **`godmode-eventtech`**: Das oberste Regelwerk für die BDB Creator Engine, das 3D, Medien und
|
|
96
|
+
- **`godmode-eventtech`**: Das oberste Regelwerk für die BDB Creator Engine, das 3D, Medien und 19 Creative-Tech MCP Wrappern steuert.
|
|
97
|
+
- **`godmode-eventtech`**: Das oberste Regelwerk für die BDB Creator Engine, das 3D, Medien und 19 Creative-Tech MCP Wrappern steuert.
|
|
98
98
|
- **`godmode-3d-creation`**: Steuert die Agentic-3D-Pipeline (TripoSR, TRELLIS) für generative Modelle und CAD-Strukturen.
|
|
99
99
|
- **`godmode-media-creation`**: Orchestriert automatisierte Videoproduktion, Storytelling und ComfyUI-Generierungsschleifen.
|
|
100
100
|
|
|
@@ -118,7 +118,7 @@ Nachfolgend finden Sie die vollständige Übersicht aller in diesem Paket enthal
|
|
|
118
118
|
|------------|-------------|
|
|
119
119
|
| `godmode-3d-creation` | Orchestrierungs-Master-Skill für alle 3D-Generierungs-, Modellierungs- und Rekonstruktionsaufgaben. Agiert als 3D-Gehirn für die BDB Creator Extension. |
|
|
120
120
|
| `godmode-engineering` | BDB Engineering Godmode. Erzwingt strenges Domain-Driven Design, TypeScript-Striktheit, Clean Architecture und systematisches 5-Stufen-Debugging. |
|
|
121
|
-
| `godmode-eventtech` | BDB EventTech Godmode. Das oberste Regelwerk für die BDB Creator Engine, das Godmode-3D, Godmode-Media und die
|
|
121
|
+
| `godmode-eventtech` | BDB EventTech Godmode. Das oberste Regelwerk für die BDB Creator Engine, das Godmode-3D, Godmode-Media und die 19 Creative-Tech MCP Wrappern steuert. |
|
|
122
122
|
| `godmode-media-creation` | Orchestrierungs-Master-Skill für alle Medienerstellungsaufgaben (Video, Audio, Bild, Motion Design). Agiert als Gehirn für die BDB Creator Extension. |
|
|
123
123
|
| `godmode-shipping` | BDB Shipping Godmode. Der finale Wächter für Production Releases. Erzwingt Spec-Driven Development, strenge Pre-Launch-Prüfungen, Feature Flags und Rollback-Strategien. |
|
|
124
124
|
| `godmode-ui-ux` | BDB UI/UX Godmode. Der absolute Goldstandard für Frontend-Design. Erzwingt Anti-Slop-Prinzipien, Enterprise-Barrierefreiheit, fluide Bewegungsdynamiken und datengestützte Design-Generierung über alle Agent-Harnesses hinweg. |
|
|
@@ -433,11 +433,11 @@ BDBrainstorm kombiniert Multi-Agenten-Brainstorming, den Slash-Befehl `/grill-me
|
|
|
433
433
|
|
|
434
434
|
---
|
|
435
435
|
|
|
436
|
-
## 🔌
|
|
436
|
+
## 🔌 19 Lokale MCP Wrapper
|
|
437
437
|
|
|
438
438
|

|
|
439
439
|
|
|
440
|
-
Anstatt sich auf rudimentäre Python-Mocks oder fehlerhafte Remote-APIs zu verlassen, bündelt dieses Repository **
|
|
440
|
+
Anstatt sich auf rudimentäre Python-Mocks oder fehlerhafte Remote-APIs zu verlassen, bündelt dieses Repository **19 eigene, lokale MCP-Wrapper** (im Ordner `mcps/`). Diese werden automatisch erstellt/aufgewärmt und ermöglichen Ihrem KI-Assistenten das Lesen, Schreiben und Ausführen von Befehlen in der führenden Kreativsoftware der Branche.
|
|
441
441
|
|
|
442
442
|
<details>
|
|
443
443
|
<summary><strong>🎨 Adobe Creative Cloud (Illustrator, Photoshop, After Effects, Premiere Pro)</strong></summary>
|
package/README.md
CHANGED
|
@@ -10,17 +10,17 @@
|
|
|
10
10
|
[](https://github.com/hybridlabor-api/aos/stargazers)
|
|
11
11
|
[](https://github.com/hybridlabor-api/aos/commits/main)
|
|
12
12
|
|
|
13
|
-
[](docs/skills_table.md)
|
|
14
14
|
[](mcps/)
|
|
15
15
|
[](#-installation)
|
|
16
16
|
[](https://github.com/hybridlabor-api/aos)
|
|
17
17
|
[](https://github.com/NVIDIA/SkillSpector)
|
|
18
18
|
|
|
19
|
-
> **Supercharging AI coding agents with
|
|
19
|
+
> **Supercharging AI coding agents with 184 hyper-curated skills, 19 local MCP wrappers, and a runnable multi-agent dispatcher graph.**
|
|
20
20
|
|
|
21
|
-
Welcome to **BDB Agent OS — AOS**:
|
|
21
|
+
Welcome to **BDB Agent OS — AOS**: 184 curated skills, 19 local MCP wrappers, an optional Hardware & PCB design module, and a dispatcher graph that turns all of it into a real multi-agent build pipeline, not just a prompt library. Point it at a goal and it plans, builds, reviews, and ships through seven coordinated agent nodes — with a mechanically enforced gate before anything actually goes live.
|
|
22
22
|
|
|
23
|
-
**Current release:** `v4.
|
|
23
|
+
**Current release:** `v4.5.0` — see the NPM badge above for the exact published version.
|
|
24
24
|
|
|
25
25
|
It is harness-neutral by design, not "optimized for one tool with others as an afterthought": the dispatcher graph runs on Claude Code's Dynamic Workflows, the same skills and MCP configuration install natively into **Google Antigravity, ChatGPT Codex / Codex CLI, Claude Desktop, Cursor, Aider, Roo Code, Cline, and Windsurf**, and the lightweight `/startcycle-graph-user` variant falls back to Claude Code's own subagents on any machine that has none of the above installed.
|
|
26
26
|
|
|
@@ -98,16 +98,16 @@ separately if you want the same routing available outside a `/startcycle` run.
|
|
|
98
98
|
## Overview
|
|
99
99
|
|
|
100
100
|
This repo ships three things: a curated skill library for coding agents, an
|
|
101
|
-
installer that wires them (plus
|
|
101
|
+
installer that wires them (plus 19 local MCP wrappers) into whichever harness
|
|
102
102
|
you use, and a dispatcher graph that orchestrates them as a multi-agent
|
|
103
103
|
build pipeline. See [AOS: The Dispatcher Graph](#-aos-the-dispatcher-graph)
|
|
104
104
|
below for how the pipeline itself works.
|
|
105
105
|
|
|
106
106
|
---
|
|
107
107
|
|
|
108
|
-
## 🌟
|
|
108
|
+
## 🌟 184 Optimized Skills
|
|
109
109
|
|
|
110
|
-
We started with a massive pool of over 1,400 raw AI skills. After rigorous testing, filtering, and refinement, we've distilled them down to a hyper-curated set of **
|
|
110
|
+
We started with a massive pool of over 1,400 raw AI skills. After rigorous testing, filtering, and refinement, we've distilled them down to a hyper-curated set of **184 Optimized Skills** (featuring a native OpenWiki documentation engine, the **memB local semantic memory brain**, and **Universal Agent Harness synchronization**).
|
|
111
111
|
|
|
112
112
|
These skills are precision-engineered to ensure agents waste no time on redundant tasks and instead operate with maximum agency, strict architectural constraints, and robust context awareness.
|
|
113
113
|
|
|
@@ -138,7 +138,7 @@ While heavily optimized for the creative tech industry, these skills are deeply
|
|
|
138
138
|
|
|
139
139
|
## 🗂️ The Complete Skill Library
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
184 skills across 15 domains, collapsed by default so this section does not require endless scrolling to get past. Click any category to expand it.
|
|
142
142
|
|
|
143
143
|
<details>
|
|
144
144
|
<summary><strong>🎨 Frontend & UI/UX Design</strong> — 20 skills</summary>
|
|
@@ -482,11 +482,11 @@ BDBrainstorm combines multi-agent brainstorming, the `/grill-me` slash command,
|
|
|
482
482
|
|
|
483
483
|
---
|
|
484
484
|
|
|
485
|
-
## 🔌
|
|
485
|
+
## 🔌 19 Local MCP Wrappers
|
|
486
486
|
|
|
487
487
|

|
|
488
488
|
|
|
489
|
-
Rather than relying on skeletal python mocks or broken remote APIs, this repository bundles **
|
|
489
|
+
Rather than relying on skeletal python mocks or broken remote APIs, this repository bundles **19 local MCP wrappers** (in the `mcps/` directory). These are built/warmed automatically and allow your AI assistant to read, write, and execute commands within the industry's leading creative software.
|
|
490
490
|
|
|
491
491
|
<details>
|
|
492
492
|
<summary><strong>🎨 Adobe Creative Cloud (Illustrator, Photoshop, After Effects, Premiere Pro)</strong></summary>
|
package/README.pt.md
CHANGED
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
[](https://www.npmjs.com/package/@hybridlabor-api/aos)
|
|
21
21
|
[](https://github.com/hybridlabor-api/aos)
|
|
22
22
|
[](LICENSE)
|
|
23
|
-
[](https://github.com/hybridlabor-api/aos)
|
|
24
24
|
[](https://github.com/NVIDIA/SkillSpector)
|
|
25
25
|
|
|
26
|
-
> **Potencializando agentes de código de IA com
|
|
26
|
+
> **Potencializando agentes de código de IA com 184 skills hipercuradas, 19 wrappers MCP locais e um grafo dispatcher de multi-agentes executável.**
|
|
27
27
|
|
|
28
|
-
Bem-vindo ao **BDB Agent OS — AOS**:
|
|
28
|
+
Bem-vindo ao **BDB Agent OS — AOS**: 184 skills curadas, 19 wrappers MCP locais e um grafo dispatcher que os transforma em um verdadeiro pipeline de build multi-agente, não apenas uma biblioteca de prompts. Aponte para um objetivo e ele planeja, constrói, revisa e implementa através de sete nós de agentes coordenados — com um portão imposto mecanicamente antes que qualquer coisa vá ao ar.
|
|
29
29
|
|
|
30
30
|
É neutro em relação ao harness por design, não "otimizado para uma ferramenta com outras como reflexão tardia": o grafo dispatcher é executado no Dynamic Workflows do Claude Code, as mesmas skills e configuração MCP são instaladas nativamente no **Google Antigravity, ChatGPT Codex / Codex CLI, Claude Desktop, Cursor, Aider, Roo Code, Cline e Windsurf**, e a variante leve `/startcycle-graph-user` recorre aos próprios subagentes do Claude Code em qualquer máquina que não tenha nenhum dos acima instalados.
|
|
31
31
|
|
|
@@ -81,14 +81,14 @@ Nenhum destes vem dentro deste pacote — são plugins do Claude Code independen
|
|
|
81
81
|
## Visão Geral
|
|
82
82
|
|
|
83
83
|
Este repositório entrega três coisas: uma biblioteca curada de skills para agentes de código, um
|
|
84
|
-
instalador que conecta eles (mais
|
|
84
|
+
instalador que conecta eles (mais 19 wrappers MCP locais) em qualquer harness
|
|
85
85
|
que você use, e um grafo dispatcher que os orquestra como um pipeline de
|
|
86
86
|
build multi-agente. Veja [AOS: O Grafo Dispatcher](#-aos-o-grafo-dispatcher)
|
|
87
87
|
abaixo para entender como o próprio pipeline funciona.
|
|
88
88
|
|
|
89
|
-
## 🌟
|
|
89
|
+
## 🌟 184 Skills Otimizadas
|
|
90
90
|
|
|
91
|
-
Começamos com um conjunto massivo de mais de 1.400 skills de IA brutas. Após rigorosos testes, filtragem e refinamento, destilamo-las em um conjunto hipercurado de **
|
|
91
|
+
Começamos com um conjunto massivo de mais de 1.400 skills de IA brutas. Após rigorosos testes, filtragem e refinamento, destilamo-las em um conjunto hipercurado de **184 Skills Otimizadas** (apresentando um motor nativo de documentação OpenWiki, o **cérebro de memória semântica local memB** e agora a **sincronização Universal Agent Harness na v4.0.0**).
|
|
92
92
|
|
|
93
93
|
Essas skills são projetadas com precisão para garantir que os agentes não percam tempo com tarefas redundantes e, em vez disso, operem com máxima autonomia, restrições arquitetônicas rígidas e robusta consciência de contexto.
|
|
94
94
|
|
|
@@ -97,7 +97,7 @@ Em vez de deixar os agentes vagando por instruções genéricas, o nível superi
|
|
|
97
97
|
- **`godmode-engineering`**: Impõe Domain-Driven Design, verificações rígidas de TypeScript, Clean Architecture e depuração sistemática.
|
|
98
98
|
- **`godmode-ui-ux`**: O padrão de ouro do frontend. Impõe princípios "Anti-Slop" da BDB, acessibilidade e dinâmicas de movimento fluidas.
|
|
99
99
|
- **`godmode-shipping`**: O guardião final para lançamentos em produção. Impõe Spec-Driven Development, verificações pré-lançamento e rollbacks seguros.
|
|
100
|
-
- **`godmode-eventtech`**: O livro de regras supremo para o BDB Creator Engine, governando 3D, Mídia e
|
|
100
|
+
- **`godmode-eventtech`**: O livro de regras supremo para o BDB Creator Engine, governando 3D, Mídia e 19 wrappers MCP de tecnologia criativa.
|
|
101
101
|
- **`godmode-3d-creation`**: Controla o pipeline 3D agêntico (TripoSR, TRELLIS) para modelos generativos e estruturas CAD.
|
|
102
102
|
- **`godmode-media-creation`**: Orquestra a produção automatizada de vídeo, narrativa e loops de geração do ComfyUI.
|
|
103
103
|
|
|
@@ -121,7 +121,7 @@ Abaixo está a visão geral completa de todas as skills curadas de agentes inclu
|
|
|
121
121
|
|------------|-------------|
|
|
122
122
|
| `godmode-3d-creation` | Skill mestre de orquestração para todas as tarefas de geração, modelagem e reconstrução 3D. Atua como o cérebro 3D para a BDB Creator Extension. |
|
|
123
123
|
| `godmode-engineering` | BDB Engineering Godmode. Impõe Domain-Driven Design rigoroso, estrito TypeScript, Clean Architecture e triagem sistemática de depuração em 5 etapas. |
|
|
124
|
-
| `godmode-eventtech` | BDB EventTech Godmode. O livro de regras supremo para o BDB Creator Engine, governando Godmode-3D, Godmode-Media e os
|
|
124
|
+
| `godmode-eventtech` | BDB EventTech Godmode. O livro de regras supremo para o BDB Creator Engine, governando Godmode-3D, Godmode-Media e os 19 wrappers MCP de tecnologia criativa. |
|
|
125
125
|
| `godmode-media-creation` | Skill mestre de orquestração para todas as tarefas de criação de mídia (Vídeo, Áudio, Imagem, Motion Design). Atua como o cérebro para a BDB Creator Extension. |
|
|
126
126
|
| `godmode-shipping` | BDB Shipping Godmode. O guardião final para lançamentos em produção. Impõe Spec-Driven Development, rigorosas verificações pré-lançamento, feature flags e estratégias de rollback. |
|
|
127
127
|
| `godmode-ui-ux` | BDB UI/UX Godmode. O padrão de ouro absoluto para design frontend. Impõe princípios Anti-Slop, acessibilidade corporativa, dinâmicas de movimento fluidas e geração de design orientada a dados em todos os harnesses de agentes. |
|
|
@@ -425,11 +425,11 @@ O BDBrainstorm combina brainstorming multi-agente, o comando slash `/grill-me`,
|
|
|
425
425
|
|
|
426
426
|
---
|
|
427
427
|
|
|
428
|
-
## 🔌
|
|
428
|
+
## 🔌 19 Integrações Locais de MCPs
|
|
429
429
|
|
|
430
430
|

|
|
431
431
|
|
|
432
|
-
Em vez de depender de mocks rudimentares em python ou APIs remotas com falhas, este repositório empacota **
|
|
432
|
+
Em vez de depender de mocks rudimentares em python ou APIs remotas com falhas, este repositório empacota **19 wrappers MCP locais** (no diretório `mcps/`). Eles são construídos/preparados automaticamente e permitem que seu assistente de IA leia, escreva e execute comandos nos principais softwares criativos do mercado.
|
|
433
433
|
|
|
434
434
|
<details>
|
|
435
435
|
<summary><strong>🎨 Adobe Creative Cloud (Illustrator, Photoshop, After Effects, Premiere Pro)</strong></summary>
|
package/installer.js
CHANGED
|
@@ -1996,6 +1996,91 @@ async function installSynapse() {
|
|
|
1996
1996
|
}
|
|
1997
1997
|
}
|
|
1998
1998
|
|
|
1999
|
+
async function installOpenWikiVisualizer() {
|
|
2000
|
+
if (DRY_RUN) {
|
|
2001
|
+
log.step('[dry-run] would register the OpenWiki Visualizer background daemon (Port 4321)');
|
|
2002
|
+
return;
|
|
2003
|
+
}
|
|
2004
|
+
if (!hasExecutable('openwiki')) {
|
|
2005
|
+
log.warn('Skipping OpenWiki Visualizer setup: the openwiki CLI was not found on PATH. Install it with: npm install -g openwiki@latest');
|
|
2006
|
+
return;
|
|
2007
|
+
}
|
|
2008
|
+
// launchd starts agents with a minimal PATH that never includes npm's global
|
|
2009
|
+
// bin dir, so resolve the absolute binary path now instead of relying on PATH at boot.
|
|
2010
|
+
let openwikiBin = 'openwiki';
|
|
2011
|
+
try {
|
|
2012
|
+
const lookup = process.platform === 'win32' ? 'where openwiki' : 'command -v openwiki';
|
|
2013
|
+
openwikiBin = execSync(lookup, { encoding: 'utf8' }).split(/\r?\n/)[0].trim() || 'openwiki';
|
|
2014
|
+
} catch (e) { logDebug(e, 'openwiki path lookup'); }
|
|
2015
|
+
|
|
2016
|
+
if (process.platform === 'darwin') {
|
|
2017
|
+
const plistPath = path.join(homeDir, 'Library', 'LaunchAgents', 'com.bdb.openwiki-visualize.plist');
|
|
2018
|
+
const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
|
|
2019
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
2020
|
+
<plist version="1.0">
|
|
2021
|
+
<dict>
|
|
2022
|
+
<key>Label</key>
|
|
2023
|
+
<string>com.bdb.openwiki-visualize</string>
|
|
2024
|
+
<key>ProgramArguments</key>
|
|
2025
|
+
<array>
|
|
2026
|
+
<string>${openwikiBin}</string>
|
|
2027
|
+
<string>visualize</string>
|
|
2028
|
+
<string>--port</string>
|
|
2029
|
+
<string>4321</string>
|
|
2030
|
+
<string>--no-open</string>
|
|
2031
|
+
</array>
|
|
2032
|
+
<key>WorkingDirectory</key>
|
|
2033
|
+
<string>${homeDir}</string>
|
|
2034
|
+
<key>RunAtLoad</key>
|
|
2035
|
+
<true/>
|
|
2036
|
+
<key>KeepAlive</key>
|
|
2037
|
+
<true/>
|
|
2038
|
+
<key>StandardOutPath</key>
|
|
2039
|
+
<string>${path.join(homeDir, '.openwiki', 'visualize.stdout.log')}</string>
|
|
2040
|
+
<key>StandardErrorPath</key>
|
|
2041
|
+
<string>${path.join(homeDir, '.openwiki', 'visualize.stderr.log')}</string>
|
|
2042
|
+
</dict>
|
|
2043
|
+
</plist>`;
|
|
2044
|
+
try {
|
|
2045
|
+
fs.mkdirSync(path.join(homeDir, '.openwiki'), { recursive: true });
|
|
2046
|
+
fs.writeFileSync(plistPath, plistContent);
|
|
2047
|
+
execSync(`launchctl unload "${plistPath}" 2>/dev/null || true`, { stdio: 'ignore' });
|
|
2048
|
+
execSync(`launchctl load -w "${plistPath}" 2>/dev/null || true`, { stdio: 'ignore' });
|
|
2049
|
+
const isListening = await verifyDaemonListening(4321, 'OpenWiki Visualizer');
|
|
2050
|
+
if (isListening) {
|
|
2051
|
+
log.success('OpenWiki Visualizer LaunchAgent active (Port 4321)');
|
|
2052
|
+
} else {
|
|
2053
|
+
log.warn('OpenWiki Visualizer daemon did not respond on Port 4321 within timeout. You may need to start it manually or check for port conflicts.');
|
|
2054
|
+
}
|
|
2055
|
+
} catch (e) { logDebug(e, 'openwiki visualizer plist setup'); }
|
|
2056
|
+
} else if (process.platform === 'win32') {
|
|
2057
|
+
const startupDir = path.join(process.env.APPDATA || path.join(homeDir, 'AppData', 'Roaming'), 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup');
|
|
2058
|
+
fs.mkdirSync(startupDir, { recursive: true });
|
|
2059
|
+
const visualizerLogDir = path.join(homeDir, '.openwiki');
|
|
2060
|
+
fs.mkdirSync(visualizerLogDir, { recursive: true });
|
|
2061
|
+
const stdoutLog = path.join(visualizerLogDir, 'visualize.stdout.log');
|
|
2062
|
+
const stderrLog = path.join(visualizerLogDir, 'visualize.stderr.log');
|
|
2063
|
+
const batPath = path.join(visualizerLogDir, 'run-openwiki-visualize.bat');
|
|
2064
|
+
const runCmd = `"${openwikiBin}" visualize --port 4321 --no-open`;
|
|
2065
|
+
const batContent = `@echo off\r\ncd /d "${homeDir}"\r\n${runCmd} >> "${stdoutLog}" 2>> "${stderrLog}"\r\n`;
|
|
2066
|
+
const vbsPath = path.join(startupDir, 'com.bdb.openwiki-visualize.vbs');
|
|
2067
|
+
const vbsContent = `Set WshShell = CreateObject("WScript.Shell")\r\nWshShell.CurrentDirectory = "${homeDir}"\r\nWshShell.Run """${batPath}""", 0, False\r\n`;
|
|
2068
|
+
try {
|
|
2069
|
+
fs.writeFileSync(batPath, batContent, 'utf-8');
|
|
2070
|
+
fs.writeFileSync(vbsPath, vbsContent, 'utf-8');
|
|
2071
|
+
spawn('wscript.exe', [vbsPath], { detached: true, stdio: 'ignore' }).unref();
|
|
2072
|
+
// Same reasoning as the Synapse Windows path: wscript -> WshShell.Run is
|
|
2073
|
+
// multiple layers of indirection, so allow the generous 12s budget here too.
|
|
2074
|
+
const isListening = await verifyDaemonListening(4321, 'OpenWiki Visualizer', 12000);
|
|
2075
|
+
if (isListening) {
|
|
2076
|
+
log.success('OpenWiki Visualizer Windows Background Service registered & started (Port 4321)');
|
|
2077
|
+
} else {
|
|
2078
|
+
log.warn(`OpenWiki Visualizer Windows daemon did not respond on Port 4321 within timeout. Check ${stderrLog} for the actual error before assuming it's just slow to start.`);
|
|
2079
|
+
}
|
|
2080
|
+
} catch (e) { logDebug(e, 'windows openwiki visualizer daemon setup'); }
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
|
|
1999
2084
|
async function installCreatorExtension() {
|
|
2000
2085
|
const creatorDir = path.join(moduleBasePath(), 'bdb-dev-creator-extension');
|
|
2001
2086
|
if (!downloadOrUpdateModule('@hybridlabor-api/bdb-dev-creator-extension', creatorDir, 'BDB Creator Extension')) {
|
|
@@ -3348,6 +3433,10 @@ function generateAndOpenLaunchpad() {
|
|
|
3348
3433
|
<meta charset="UTF-8">
|
|
3349
3434
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
3350
3435
|
<title>BDB Agent OS – Launchpad</title>
|
|
3436
|
+
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48ZGVmcz48bGluZWFyR3JhZGllbnQgaWQ9ImEiIHgxPSIwJSIgeTE9IjAlIiB4Mj0iMTAwJSIgeTI9IjEwMCUiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiNGRkZGRkYiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNFN0U3RUEiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48Y2lyY2xlIGN4PSIyNTYiIGN5PSIyNTYiIHI9IjI0NiIgZmlsbD0iIzBhMGEwYSIgc3Ryb2tlPSIjOWIzMGM0IiBzdHJva2Utd2lkdGg9IjEyIi8+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNzAsNjgpIj48cGF0aCBmaWxsPSJ1cmwoI2EpIiBkPSJNMTgxLjYzLjA1YzEwMS4zOS0yLjQ3LDE4NC41Niw4MC4wOSwxOTAuMTQsMTc5LjkzLDUuNTMsOTkuMDMtNjYuMTYsMTg1LjQyLTE2NS4xMSwxOTUuNDYtODcuMzksOC44Ni0xNzEuMS00NS41Ni0xOTcuNjctMTI4Ljk2Qy0yOC43NCwxMjguMDMsNTYuNzgsMy4xLDE4MS42My4wNWgwWk0xNzcuNSwyMS4zQzY5LjA5LDI1LjMxLTcuMTYsMTI5LjYyLDIxLjc2LDIzNC41MmMxOC43Miw2Ny44OCw4MS41NiwxMTYuNywxNTEuNTMsMTIxLjMyLDEwNi4yMSw3LjAzLDE5NS42LTgxLjYzLDE3OS42OC0xODkuMDYtMTIuNTQtODQuNjUtODkuODEtMTQ4LjY2LTE3NS40Ny0xNDUuNDloMFoiLz48ZyBmaWxsPSIjRkZGRkZGIj48cGF0aCBkPSJNMTQ3LjY5LDEyMC4wNWMxMi4wNC4zNiwyNC42NC0uNzIsMzYuNjItLjA3LDI0LjI5LDEuMzIsNDEuMzcsMjAuMTMsNDIuOTEsNDMuOTktLjY5LDE2LjM1LjU3LDMzLjQyLS4yOCw0OS42OS0xLjMxLDI1LjQyLTE4LjU1LDQzLjc1LTQ0LjAyLDQ1LjY0LTkuNTkuNzItMjAuMTQuNjktMjkuNzguODQtNC45Ny4wOC05LjkuNjgtMTAuMzctNS42NnMuNDMtOS40MS4zNC0xNC4wM2MxMi42NS0xMS44NCwxNC43NS0zMS4xNyw0Ljc1LTQ1LjQxLS42My0uOS0yLjI2LTIuMzQtMi42Mi0zLjE3cy0uNDYtMTIuNTgtLjI2LTE0LjM3LDEuMS0zLjUyLDEuNDYtNS4xNmMxLjIxLTUuNDIsMS4wNi0xMS4yNi0uMzktMTYuNjItLjQxLTEuNTQtMS40OC0zLjU2LTEuNjMtNC45OS0uNDctNC4yOC0uMTQtOS42Ny0uMjYtMTQuMDgtLjExLTMuNTYtLjg0LTguNDMtLjU3LTExLjg2czEuMzItNC4zNSw0LjA4LTQuNzVoMFoiLz48cGF0aCBkPSJNMjMyLjY2LDEzMi40NmM5LjUzLjM2LDE5Ljc0LS43MiwyOS4xOS0uMDgsMjIuNjQsMS41MiwzMy45MiwyOC41OCwyMS45Myw0Ny4wNS0xLjQ5LDIuMy00LjMyLDQuNDctMy44NSw3LjQyLjQ3LDIuOTUsNS42NCw2LjIxLDcuNDIsOC4zLDExLjg4LDEzLjk2LDguNDEsMzUuNjktNi45MSw0NS40OS03Ljg1LDUuMDItMTQuNjksNC40My0yMy41Niw0Ljg2LTcuNjcuMzctMTYuMjQsMS4wNS0yMy45MS42NloiLz48cGF0aCBkPSJNOTAuNTksMTMzLjAzYzguODQtLjQ0LDI1LjI0LTEuMDgsMzMuMjMsMS45MiwxOC4wNyw2Ljc3LDIzLjk5LDI5Ljk2LDEzLjU2LDQ1LjctMS42LDIuNDEtNC41Miw0LjQ0LTMuMjgsNy43NS42OSwxLjg1LDUuNDEsNS40Miw3LjAzLDcuMzEsMTEuODYsMTMuODIsOC43NywzNS4yMy02LjI1LDQ1LjMzLTE1LjAyLDEwLjEtMjMuMzEsNS4yNy0zNC40NCw1LjU2WiIvPjwvZz48L2c+PC9zdmc+">
|
|
3437
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
3438
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
3439
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
3351
3440
|
<style>
|
|
3352
3441
|
:root {
|
|
3353
3442
|
--bg: #090a0f;
|
|
@@ -3355,10 +3444,10 @@ function generateAndOpenLaunchpad() {
|
|
|
3355
3444
|
--card-border: rgba(255, 255, 255, 0.08);
|
|
3356
3445
|
--text: #f0f6fc;
|
|
3357
3446
|
--text-muted: #8b949e;
|
|
3358
|
-
--accent: #
|
|
3447
|
+
--accent: #9b30c4;
|
|
3359
3448
|
--green: #3fb950;
|
|
3360
|
-
--font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
3361
|
-
--mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
3449
|
+
--font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
3450
|
+
--mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
3362
3451
|
}
|
|
3363
3452
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
3364
3453
|
body {
|
|
@@ -3384,12 +3473,9 @@ function generateAndOpenLaunchpad() {
|
|
|
3384
3473
|
letter-spacing: -0.5px;
|
|
3385
3474
|
margin-bottom: 6px;
|
|
3386
3475
|
}
|
|
3387
|
-
.logo-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
-webkit-text-fill-color: transparent;
|
|
3391
|
-
}
|
|
3392
|
-
.tagline { color: var(--text-muted); font-size: 14px; }
|
|
3476
|
+
.logo-mark { width: 36px; height: 36px; flex-shrink: 0; }
|
|
3477
|
+
.logo-badge { color: #ffffff; }
|
|
3478
|
+
.tagline { color: var(--text-muted); font-size: 14px; font-weight: 400; }
|
|
3393
3479
|
.grid { display: flex; flex-direction: column; gap: 12px; }
|
|
3394
3480
|
.card {
|
|
3395
3481
|
background: var(--card-bg);
|
|
@@ -3405,15 +3491,15 @@ function generateAndOpenLaunchpad() {
|
|
|
3405
3491
|
transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1);
|
|
3406
3492
|
}
|
|
3407
3493
|
.card:hover {
|
|
3408
|
-
border-color: rgba(
|
|
3494
|
+
border-color: rgba(155, 48, 196, 0.45);
|
|
3409
3495
|
transform: translateY(-2px);
|
|
3410
3496
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
|
|
3411
3497
|
}
|
|
3412
3498
|
.card-content { display: flex; align-items: center; gap: 14px; }
|
|
3413
3499
|
.card-icon {
|
|
3414
|
-
font-size: 22px;
|
|
3415
3500
|
width: 40px;
|
|
3416
3501
|
height: 40px;
|
|
3502
|
+
padding: 6px;
|
|
3417
3503
|
border-radius: 10px;
|
|
3418
3504
|
background: rgba(255, 255, 255, 0.04);
|
|
3419
3505
|
border: 1px solid rgba(255, 255, 255, 0.06);
|
|
@@ -3421,6 +3507,7 @@ function generateAndOpenLaunchpad() {
|
|
|
3421
3507
|
align-items: center;
|
|
3422
3508
|
justify-content: center;
|
|
3423
3509
|
}
|
|
3510
|
+
.card-icon svg { width: 100%; height: 100%; }
|
|
3424
3511
|
.card-info h2 { font-size: 15px; font-weight: 600; margin-bottom: 2px; }
|
|
3425
3512
|
.card-info p { font-size: 13px; color: var(--text-muted); }
|
|
3426
3513
|
.card-meta {
|
|
@@ -3434,7 +3521,7 @@ function generateAndOpenLaunchpad() {
|
|
|
3434
3521
|
background: rgba(255, 255, 255, 0.06);
|
|
3435
3522
|
padding: 4px 10px;
|
|
3436
3523
|
border-radius: 20px;
|
|
3437
|
-
color: #
|
|
3524
|
+
color: #c77dea;
|
|
3438
3525
|
}
|
|
3439
3526
|
.status-dot {
|
|
3440
3527
|
width: 8px;
|
|
@@ -3460,13 +3547,43 @@ function generateAndOpenLaunchpad() {
|
|
|
3460
3547
|
<body>
|
|
3461
3548
|
<div class="container">
|
|
3462
3549
|
<div class="header">
|
|
3463
|
-
<div class="logo"
|
|
3550
|
+
<div class="logo">
|
|
3551
|
+
<svg class="logo-mark" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
|
|
3552
|
+
<defs>
|
|
3553
|
+
<linearGradient id="bdbPlateLight" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
3554
|
+
<stop offset="0%" stop-color="#FFFFFF"/><stop offset="60%" stop-color="#FFFFFF"/><stop offset="100%" stop-color="#E7E7EA"/>
|
|
3555
|
+
</linearGradient>
|
|
3556
|
+
<linearGradient id="bdbPlateDark" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
3557
|
+
<stop offset="0%" stop-color="#1C1C1F"/><stop offset="100%" stop-color="#050505"/>
|
|
3558
|
+
</linearGradient>
|
|
3559
|
+
</defs>
|
|
3560
|
+
<circle cx="256" cy="256" r="195" fill="url(#bdbPlateDark)" stroke="#FFFFFF" stroke-width="2" stroke-opacity="0.6"/>
|
|
3561
|
+
<circle cx="256" cy="256" r="175" fill="#0a0a0a"/>
|
|
3562
|
+
<g transform="translate(70, 68) scale(1.0)">
|
|
3563
|
+
<path fill="url(#bdbPlateLight)" d="M181.63.05c101.39-2.47,184.56,80.09,190.14,179.93,5.53,99.03-66.16,185.42-165.11,195.46-87.39,8.86-171.1-45.56-197.67-128.96C-28.74,128.03,56.78,3.1,181.63.05h0ZM177.5,21.3C69.09,25.31-7.16,129.62,21.76,234.52c18.72,67.88,81.56,116.7,151.53,121.32,106.21,7.03,195.6-81.63,179.68-189.06-12.54-84.65-89.81-148.66-175.47-145.49h0Z"/>
|
|
3564
|
+
<g fill="#FFFFFF">
|
|
3565
|
+
<path d="M147.69,120.05c12.04.36,24.64-.72,36.62-.07,24.29,1.32,41.37,20.13,42.91,43.99-.69,16.35.57,33.42-.28,49.69-1.31,25.42-18.55,43.75-44.02,45.64-9.59.72-20.14.69-29.78.84-4.97.08-9.9.68-10.37-5.66s.43-9.41.34-14.03c12.65-11.84,14.75-31.17,4.75-45.41-.63-.9-2.26-2.34-2.62-3.17s-.46-12.58-.26-14.37,1.1-3.52,1.46-5.16c1.21-5.42,1.06-11.26-.39-16.62-.41-1.54-1.48-3.56-1.63-4.99-.47-4.28-.14-9.67-.26-14.08-.11-3.56-.84-8.43-.57-11.86s1.32-4.35,4.08-4.75h0ZM162.03,135.5c-4.32.73-3.34,6.65-3.26,10.01.17,6.21.91,12.51,1.13,18.73.83,23.13-1.03,45.49-1.41,68.42-.07,3.93-1.27,10.87,4.01,11.46,10.36-.51,21.39,1.89,31.38-1.45,13.74-4.59,20.43-17.79,19.81-31.81-1.77-14.46-1.19-29.09-1.94-43.58-.52-10.12-3.97-20.33-12.44-26.46-10.8-7.82-24.82-4.88-37.29-5.34h0Z"/>
|
|
3566
|
+
<path d="M232.66,132.46c9.53.36,19.74-.72,29.19-.08,22.64,1.52,33.92,28.58,21.93,47.05-1.49,2.3-4.32,4.47-3.85,7.42.47,2.95,5.64,6.21,7.42,8.3,11.88,13.96,8.41,35.69-6.91,45.49-7.85,5.02-14.69,4.43-23.56,4.86-7.67.37-16.24,1.05-23.91.66-1.66-.08-2.98-.73-3.68-2.32s-.52-7.28-.43-9.26c.36-6.63,3.52-13.04,3.89-20.39.58-11.38-.1-23.12-.3-34.49-.1-5.68.32-11.44-.3-17.08-.41-3.82-1.64-7.52-1.89-11.35-.25-3.85-.18-7.99-.26-11.88-.07-2.84-1.26-6.03,2.68-6.95h-.01ZM243.68,144.59c-3.41.77-2.55,6.7-2.66,9.2-.28,6.08-.58,12.36-.29,18.47.1,2.06.36,6.36.9,8.21.54,1.85.84,1.79,1.66,2.19,1.66.83,8-.68,10.26-.88,4.22-.39,8.12.03,12.28-1.24,16.76-5.12,16.53-26.53,1.01-33.02-15.52-6.5-13.5-2.7-18.82-2.98-5.31-.28-3.37-.17-4.36.06h.03ZM243.68,194.52c-3.49.79-2.58,8.66-2.68,11.39-.26,7.05-1.06,17.41.07,24.21,1.13,6.8,2.63,3.38,5.32,3.26,3.96-.19,8.36-1.32,12.4-1.67,5.85-.5,10.68.22,16.24-2.25,13.6-6.04,12.62-25.27-.46-31.46-5.63-2.66-9.89-1.97-15.78-2.43-3.57-.28-7.2-.92-10.76-1.1-1.12-.06-3.35-.17-4.36.06h0Z"/>
|
|
3567
|
+
<path d="M90.59,133.03c8.84-.44,25.24-1.08,33.23,1.92,18.07,6.77,23.99,29.96,13.56,45.7-1.6,2.41-4.52,4.44-3.28,7.75.69,1.85,5.41,5.42,7.03,7.31,11.86,13.82,8.77,35.23-6.25,45.33-15.02,10.1-23.31,5.27-34.44,5.56-4.12.11-10.36.88-14.32.28-2.22-.34-3.45-2.79-3.48-4.83-.11-7.84.77-15.89,1.1-23.71.99-23.09,1.31-45.33.57-68.43-.14-4.15-1.05-9.79-.57-13.79.43-3.52,4.1-2.95,6.84-3.09h0ZM98.3,145.15c-1.71.29-2.98,1.7-3.21,3.41-.15,1.19-.23,3.13-.3,4.39-.39,8.01-.9,19.53.58,27.27.23,1.24.57,2.55,1.82,3.15,1.81.84,7.03-.55,9.32-.76,3.3-.3,6.62-.1,9.89-.59,21.2-3.21,21.02-29.7,1.28-34.86-4.36-1.14-13.16-1.92-17.79-2.07-.55-.01-1.03-.03-1.59.07h0ZM98.03,195.09c-4.25.88-2.46,6.76-3.24,9.72-.06,7.92-.55,15.86,0,23.75.22,3.21.77,5.75,4.57,5.67,3.82-.08,8.46-1.32,12.41-1.67,5.55-.48,11.21.12,16.48-2,14.62-5.88,13.53-26.13-.52-32.17-5.13-2.21-8.25-1.59-13.48-1.97-4.69-.34-9.7-1.23-14.35-1.38-.62-.01-1.26-.07-1.86.06h-.01Z"/>
|
|
3568
|
+
</g>
|
|
3569
|
+
</g>
|
|
3570
|
+
</svg>
|
|
3571
|
+
<span class="logo-badge">BDB Agent OS</span>
|
|
3572
|
+
</div>
|
|
3464
3573
|
<p class="tagline">Local Multi-Agent Ecosystem Hub</p>
|
|
3465
3574
|
</div>
|
|
3466
3575
|
<div class="grid">
|
|
3467
3576
|
<a class="card" href="http://127.0.0.1:8088" target="_blank">
|
|
3468
3577
|
<div class="card-content">
|
|
3469
|
-
<div class="card-icon"
|
|
3578
|
+
<div class="card-icon"><svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
|
|
3579
|
+
<defs><linearGradient id="grad-memb" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#FFFFFF"/><stop offset="100%" stop-color="#51116F"/></linearGradient></defs>
|
|
3580
|
+
<polygon points="50,10 85,45 50,90 15,45" fill="url(#grad-memb)" opacity="0.9"/>
|
|
3581
|
+
<polyline points="50,10 50,90" stroke="#FFFFFF" stroke-width="2" opacity="0.6"/>
|
|
3582
|
+
<polyline points="15,45 85,45" stroke="#FFFFFF" stroke-width="2" opacity="0.6"/>
|
|
3583
|
+
<line x1="50" y1="45" x2="70" y2="25" stroke="#FFFFFF" stroke-width="1.5" opacity="0.5"/>
|
|
3584
|
+
<line x1="50" y1="45" x2="30" y2="70" stroke="#FFFFFF" stroke-width="1.5" opacity="0.5"/>
|
|
3585
|
+
<circle cx="50" cy="45" r="4" fill="#FFFFFF"/><circle cx="70" cy="25" r="2" fill="#FFFFFF"/><circle cx="30" cy="70" r="2" fill="#FFFFFF"/>
|
|
3586
|
+
</svg></div>
|
|
3470
3587
|
<div class="card-info">
|
|
3471
3588
|
<h2>memB Vector Memory</h2>
|
|
3472
3589
|
<p>Autonomous Vector & Long-Term Memory</p>
|
|
@@ -3479,7 +3596,15 @@ function generateAndOpenLaunchpad() {
|
|
|
3479
3596
|
</a>
|
|
3480
3597
|
<a class="card" href="http://127.0.0.1:7781" target="_blank">
|
|
3481
3598
|
<div class="card-content">
|
|
3482
|
-
<div class="card-icon"
|
|
3599
|
+
<div class="card-icon"><svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
|
|
3600
|
+
<defs><linearGradient id="grad-synapse" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#FFFFFF"/><stop offset="100%" stop-color="#51116F"/></linearGradient></defs>
|
|
3601
|
+
<rect x="20" y="55" width="14" height="30" rx="2" fill="url(#grad-synapse)" opacity="0.85"/>
|
|
3602
|
+
<rect x="43" y="35" width="14" height="50" rx="2" fill="url(#grad-synapse)" opacity="0.9"/>
|
|
3603
|
+
<rect x="66" y="45" width="14" height="40" rx="2" fill="url(#grad-synapse)" opacity="0.8"/>
|
|
3604
|
+
<line x1="27" y1="55" x2="50" y2="35" stroke="#FFFFFF" stroke-width="1.5" opacity="0.5"/>
|
|
3605
|
+
<line x1="50" y1="35" x2="73" y2="45" stroke="#FFFFFF" stroke-width="1.5" opacity="0.5"/>
|
|
3606
|
+
<circle cx="27" cy="55" r="3" fill="#FFFFFF"/><circle cx="50" cy="35" r="3" fill="#FFFFFF"/><circle cx="73" cy="45" r="3" fill="#FFFFFF"/>
|
|
3607
|
+
</svg></div>
|
|
3483
3608
|
<div class="card-info">
|
|
3484
3609
|
<h2>Synapse 3D</h2>
|
|
3485
3610
|
<p>Interactive Codebase Topology & Sessions</p>
|
|
@@ -3492,7 +3617,40 @@ function generateAndOpenLaunchpad() {
|
|
|
3492
3617
|
</a>
|
|
3493
3618
|
<a class="card" href="http://127.0.0.1:3101" target="_blank">
|
|
3494
3619
|
<div class="card-content">
|
|
3495
|
-
<div class="card-icon"
|
|
3620
|
+
<div class="card-icon"><svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
|
|
3621
|
+
<defs>
|
|
3622
|
+
<linearGradient id="plateLight" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="#FFFFFF"/><stop offset="60%" stop-color="#FFFFFF"/><stop offset="100%" stop-color="#E7E7EA"/></linearGradient>
|
|
3623
|
+
<linearGradient id="plateMid" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="#9b30c4"/><stop offset="100%" stop-color="#51116F"/></linearGradient>
|
|
3624
|
+
<linearGradient id="plateDark" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="#1C1C1F"/><stop offset="100%" stop-color="#050505"/></linearGradient>
|
|
3625
|
+
</defs>
|
|
3626
|
+
<g id="antennae" stroke="#000000" stroke-width="2.5" stroke-linejoin="round">
|
|
3627
|
+
<rect x="180" y="45" width="20" height="30" rx="2" fill="url(#plateLight)"/><polygon points="180,45 190,25 200,45" fill="#FFFFFF"/><circle cx="190" cy="25" r="4" fill="#FFFFFF"/>
|
|
3628
|
+
<rect x="186" y="80" width="22" height="34" rx="2" fill="url(#plateMid)"/><rect x="194" y="118" width="24" height="38" rx="2" fill="url(#plateDark)"/><rect x="202" y="160" width="26" height="38" rx="2" fill="url(#plateDark)"/>
|
|
3629
|
+
<rect x="312" y="45" width="20" height="30" rx="2" fill="url(#plateLight)"/><polygon points="312,45 322,25 332,45" fill="#FFFFFF"/><circle cx="322" cy="25" r="4" fill="#FFFFFF"/>
|
|
3630
|
+
<rect x="304" y="80" width="22" height="34" rx="2" fill="url(#plateMid)"/><rect x="294" y="118" width="24" height="38" rx="2" fill="url(#plateDark)"/><rect x="284" y="160" width="26" height="38" rx="2" fill="url(#plateDark)"/>
|
|
3631
|
+
</g>
|
|
3632
|
+
<g id="head" stroke="#000000" stroke-width="2.5" stroke-linejoin="round">
|
|
3633
|
+
<rect x="238" y="170" width="36" height="32" rx="3" fill="url(#plateLight)"/>
|
|
3634
|
+
<rect x="156" y="206" width="200" height="88" rx="6" fill="url(#plateDark)"/>
|
|
3635
|
+
<rect x="136" y="230" width="20" height="40" rx="3" fill="url(#plateMid)"/><rect x="356" y="230" width="20" height="40" rx="3" fill="url(#plateMid)"/>
|
|
3636
|
+
</g>
|
|
3637
|
+
<g id="eyes">
|
|
3638
|
+
<rect x="174" y="222" width="56" height="52" rx="5" fill="#000000" stroke="#FFFFFF" stroke-width="2"/><rect x="180" y="228" width="44" height="40" rx="3" fill="url(#plateDark)"/>
|
|
3639
|
+
<circle cx="202" cy="248" r="14" fill="#FFFFFF" opacity="0.3"/><circle cx="202" cy="248" r="7" fill="#FFFFFF"/><circle cx="205" cy="245" r="2.5" fill="#FFFFFF"/>
|
|
3640
|
+
<rect x="282" y="222" width="56" height="52" rx="5" fill="#000000" stroke="#FFFFFF" stroke-width="2"/><rect x="288" y="228" width="44" height="40" rx="3" fill="url(#plateDark)"/>
|
|
3641
|
+
<circle cx="310" cy="248" r="14" fill="#FFFFFF" opacity="0.3"/><circle cx="310" cy="248" r="7" fill="#FFFFFF"/><circle cx="313" cy="245" r="2.5" fill="#FFFFFF"/>
|
|
3642
|
+
</g>
|
|
3643
|
+
<g id="mandibles" stroke="#000000" stroke-width="2.5">
|
|
3644
|
+
<rect x="226" y="298" width="60" height="18" rx="3" fill="url(#plateLight)"/>
|
|
3645
|
+
<rect x="236" y="303" width="10" height="8" rx="1.5" fill="#51116F"/><rect x="251" y="303" width="10" height="8" rx="1.5" fill="#51116F"/><rect x="266" y="303" width="10" height="8" rx="1.5" fill="#51116F"/>
|
|
3646
|
+
<polygon points="196,300 220,300 206,340" fill="url(#plateLight)"/><polygon points="316,300 292,300 306,340" fill="url(#plateLight)"/>
|
|
3647
|
+
</g>
|
|
3648
|
+
<g id="thorax" stroke="#000000" stroke-width="2.5" stroke-linejoin="round">
|
|
3649
|
+
<rect x="180" y="336" width="152" height="74" rx="6" fill="url(#plateMid)"/>
|
|
3650
|
+
<rect x="216" y="352" width="80" height="42" rx="4" fill="#0c0414" stroke="#FFFFFF" stroke-width="1.5"/>
|
|
3651
|
+
<text x="256" y="378" fill="#FFFFFF" font-family="monospace" font-size="14" font-weight="900" text-anchor="middle" letter-spacing="3">BDB</text>
|
|
3652
|
+
</g>
|
|
3653
|
+
</svg></div>
|
|
3496
3654
|
<div class="card-info">
|
|
3497
3655
|
<h2>AO — Agent Orchestrator</h2>
|
|
3498
3656
|
<p>Multi-Agent Cockpit & Git-Worktree Orchestration</p>
|
|
@@ -3505,7 +3663,15 @@ function generateAndOpenLaunchpad() {
|
|
|
3505
3663
|
</a>
|
|
3506
3664
|
<a class="card" href="http://127.0.0.1:9080" target="_blank">
|
|
3507
3665
|
<div class="card-content">
|
|
3508
|
-
<div class="card-icon"
|
|
3666
|
+
<div class="card-icon"><svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
|
|
3667
|
+
<defs><linearGradient id="grad-remote" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#FFFFFF"/><stop offset="100%" stop-color="#51116F"/></linearGradient></defs>
|
|
3668
|
+
<circle cx="50" cy="50" r="32" fill="none" stroke="url(#grad-remote)" stroke-width="3" opacity="0.6"/>
|
|
3669
|
+
<circle cx="50" cy="50" r="8" fill="url(#grad-remote)"/>
|
|
3670
|
+
<circle cx="50" cy="14" r="4" fill="#FFFFFF"/><circle cx="82" cy="65" r="4" fill="#FFFFFF"/><circle cx="18" cy="65" r="4" fill="#FFFFFF"/>
|
|
3671
|
+
<line x1="50" y1="50" x2="50" y2="18" stroke="#FFFFFF" stroke-width="1.5" opacity="0.6"/>
|
|
3672
|
+
<line x1="50" y1="50" x2="79" y2="63" stroke="#FFFFFF" stroke-width="1.5" opacity="0.6"/>
|
|
3673
|
+
<line x1="50" y1="50" x2="21" y2="63" stroke="#FFFFFF" stroke-width="1.5" opacity="0.6"/>
|
|
3674
|
+
</svg></div>
|
|
3509
3675
|
<div class="card-info">
|
|
3510
3676
|
<h2>RemoteOS Gateway</h2>
|
|
3511
3677
|
<p>Multi-Cloud Execution & 4-Eyes Approval Gateway</p>
|
|
@@ -3516,6 +3682,30 @@ function generateAndOpenLaunchpad() {
|
|
|
3516
3682
|
<span class="status-dot" id="dot-remote" title="Checking..."></span>
|
|
3517
3683
|
</div>
|
|
3518
3684
|
</a>
|
|
3685
|
+
<a class="card" href="http://127.0.0.1:4321" target="_blank">
|
|
3686
|
+
<div class="card-content">
|
|
3687
|
+
<div class="card-icon"><svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
|
|
3688
|
+
<defs><linearGradient id="grad-openwiki" x1="50%" y1="0%" x2="50%" y2="100%"><stop offset="0%" stop-color="#FFFFFF"/><stop offset="100%" stop-color="#51116F"/></linearGradient></defs>
|
|
3689
|
+
<rect x="26" y="16" width="48" height="68" rx="4" fill="url(#grad-openwiki)" opacity="0.9"/>
|
|
3690
|
+
<line x1="36" y1="32" x2="64" y2="32" stroke="#0a0a0a" stroke-width="2.5" opacity="0.5"/>
|
|
3691
|
+
<line x1="36" y1="42" x2="64" y2="42" stroke="#0a0a0a" stroke-width="2.5" opacity="0.5"/>
|
|
3692
|
+
<line x1="36" y1="52" x2="52" y2="52" stroke="#0a0a0a" stroke-width="2.5" opacity="0.5"/>
|
|
3693
|
+
<circle cx="70" cy="68" r="14" fill="#0a0a0a" stroke="#FFFFFF" stroke-width="2"/>
|
|
3694
|
+
<circle cx="65" cy="64" r="2.5" fill="#FFFFFF"/><circle cx="74" cy="63" r="2.5" fill="#FFFFFF"/><circle cx="70" cy="72" r="2.5" fill="#FFFFFF"/>
|
|
3695
|
+
<line x1="65" y1="64" x2="74" y2="63" stroke="#FFFFFF" stroke-width="1.2" opacity="0.7"/>
|
|
3696
|
+
<line x1="65" y1="64" x2="70" y2="72" stroke="#FFFFFF" stroke-width="1.2" opacity="0.7"/>
|
|
3697
|
+
<line x1="74" y1="63" x2="70" y2="72" stroke="#FFFFFF" stroke-width="1.2" opacity="0.7"/>
|
|
3698
|
+
</svg></div>
|
|
3699
|
+
<div class="card-info">
|
|
3700
|
+
<h2>OpenWiki</h2>
|
|
3701
|
+
<p>Grounded Documentation & Evidence Graph</p>
|
|
3702
|
+
</div>
|
|
3703
|
+
</div>
|
|
3704
|
+
<div class="card-meta">
|
|
3705
|
+
<span class="port-pill">:4321</span>
|
|
3706
|
+
<span class="status-dot" id="dot-openwiki" title="Checking..."></span>
|
|
3707
|
+
</div>
|
|
3708
|
+
</a>
|
|
3519
3709
|
</div>
|
|
3520
3710
|
<div class="footer">
|
|
3521
3711
|
<span>Autostart Daemons • 127.0.0.1</span>
|
|
@@ -3534,6 +3724,7 @@ function generateAndOpenLaunchpad() {
|
|
|
3534
3724
|
checkHealth('http://127.0.0.1:7781', 'dot-synapse');
|
|
3535
3725
|
checkHealth('http://127.0.0.1:3101', 'dot-ao');
|
|
3536
3726
|
checkHealth('http://127.0.0.1:9080', 'dot-remote');
|
|
3727
|
+
checkHealth('http://127.0.0.1:4321', 'dot-openwiki');
|
|
3537
3728
|
}
|
|
3538
3729
|
checkAllHealth();
|
|
3539
3730
|
setInterval(checkAllHealth, 5000);
|
|
@@ -3761,6 +3952,7 @@ async function runQuickUpdate(installState) {
|
|
|
3761
3952
|
const creds = await promptCredentials(paths.targetMcpDir);
|
|
3762
3953
|
if (creds !== BACK) {
|
|
3763
3954
|
await installOpenWikiDaemon(creds.gemini, paths.targetSkillDir, { provider: creds.openwikiProvider, model: creds.openwikiModel, baseUrl: creds.openwikiBaseUrl });
|
|
3955
|
+
await installOpenWikiVisualizer();
|
|
3764
3956
|
}
|
|
3765
3957
|
}
|
|
3766
3958
|
|
|
@@ -4173,6 +4365,7 @@ async function main() {
|
|
|
4173
4365
|
}
|
|
4174
4366
|
|
|
4175
4367
|
await installOpenWikiDaemon(creds.gemini, primaryTarget.targetSkillDir, { provider: creds.openwikiProvider, model: creds.openwikiModel, baseUrl: creds.openwikiBaseUrl });
|
|
4368
|
+
await installOpenWikiVisualizer();
|
|
4176
4369
|
await installTokenSaver(primaryTarget.platformValue);
|
|
4177
4370
|
|
|
4178
4371
|
const installedModulesForPrompt = (installState && installState.installedModules) || [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hybridlabor-api/aos",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.0",
|
|
4
4
|
"description": "AOS — A Curated AI AGENT OS. Optimized agent skills and add-ons like memB, OpenWiki, Heimdall Token Saver, and Godmode architectures.",
|
|
5
5
|
"main": "installer.js",
|
|
6
6
|
"engines": {
|
|
@@ -26,35 +26,84 @@ try {
|
|
|
26
26
|
Write-Host "Warning: pip install failed. Install google-genai manually." -ForegroundColor Yellow
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
# 3. Resolve API key
|
|
30
|
-
$
|
|
31
|
-
if ([string]::IsNullOrWhiteSpace($
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
$
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
29
|
+
# 3. Resolve provider and API key
|
|
30
|
+
$OpenwikiProvider = $env:OPENWIKI_PROVIDER
|
|
31
|
+
if ([string]::IsNullOrWhiteSpace($OpenwikiProvider)) {
|
|
32
|
+
$OpenwikiProvider = "google"
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# Map provider to its API key environment variable name
|
|
36
|
+
$ApiKeyVar = switch ($OpenwikiProvider) {
|
|
37
|
+
"google" { "GEMINI_API_KEY" }
|
|
38
|
+
"groq" { "GROQ_API_KEY" }
|
|
39
|
+
"grok" { "XAI_API_KEY" }
|
|
40
|
+
"xai" { "XAI_API_KEY" }
|
|
41
|
+
"nvidia" { "NVIDIA_API_KEY" }
|
|
42
|
+
"openrouter" { "OPENROUTER_API_KEY" }
|
|
43
|
+
"openai" { "OPENAI_API_KEY" }
|
|
44
|
+
"custom" { "OPENWIKI_API_KEY" }
|
|
45
|
+
"ollama" { $null }
|
|
46
|
+
default { "GEMINI_API_KEY"; $OpenwikiProvider = "google" }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# For Google provider, use the existing interactive flow with verification
|
|
50
|
+
if ($OpenwikiProvider -eq "google") {
|
|
51
|
+
$ApiKey = $env:GEMINI_API_KEY
|
|
52
|
+
if ([string]::IsNullOrWhiteSpace($ApiKey)) {
|
|
53
|
+
Write-Host ""
|
|
54
|
+
$ApiKey = Read-Host "Enter your Gemini API key (or press Enter to skip)"
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (-not [string]::IsNullOrWhiteSpace($ApiKey)) {
|
|
58
|
+
Write-Host "Verifying API key..." -ForegroundColor Yellow
|
|
59
|
+
# verify_api_key.py reads GEMINI_API_KEY from its own process environment.
|
|
60
|
+
# A key typed at the Read-Host prompt above exists only in $ApiKey, so it
|
|
61
|
+
# has to be published to this process before python is started - otherwise
|
|
62
|
+
# the child sees nothing and every interactively entered key fails the check
|
|
63
|
+
# and is discarded below.
|
|
64
|
+
$env:GEMINI_API_KEY = $ApiKey
|
|
65
|
+
$VerifyScript = Join-Path $PSScriptRoot "verify_api_key.py"
|
|
66
|
+
$VerifyOutput = & python $VerifyScript 2>&1
|
|
67
|
+
$VerifyCode = $LASTEXITCODE
|
|
68
|
+
if ($VerifyCode -eq 0 -and ($VerifyOutput -match "VERIFIED_OK")) {
|
|
69
|
+
Write-Host " -> API key verified." -ForegroundColor Green
|
|
70
|
+
[System.Environment]::SetEnvironmentVariable("GEMINI_API_KEY", $ApiKey, "User")
|
|
71
|
+
} else {
|
|
72
|
+
Write-Host " -> WARNING: API key verification failed (with retry + TLS fallback)." -ForegroundColor Yellow
|
|
73
|
+
$VerifyOutput | ForEach-Object { Write-Host " $_" -ForegroundColor DarkGray }
|
|
74
|
+
Write-Host " The daemon will run in collect-only mode until a valid key is set." -ForegroundColor Yellow
|
|
75
|
+
$ApiKey = ""
|
|
76
|
+
}
|
|
50
77
|
} else {
|
|
51
|
-
Write-Host "
|
|
52
|
-
$VerifyOutput | ForEach-Object { Write-Host " $_" -ForegroundColor DarkGray }
|
|
53
|
-
Write-Host " The daemon will run in collect-only mode until a valid key is set." -ForegroundColor Yellow
|
|
54
|
-
$GeminiKey = ""
|
|
78
|
+
Write-Host "No API key provided. Daemon will run in collect-only mode." -ForegroundColor Yellow
|
|
55
79
|
}
|
|
56
80
|
} else {
|
|
57
|
-
|
|
81
|
+
# For non-Google providers, skip verification and use the configured key
|
|
82
|
+
if ([string]::IsNullOrWhiteSpace($ApiKeyVar)) {
|
|
83
|
+
$ApiKey = ""
|
|
84
|
+
} else {
|
|
85
|
+
$ApiKey = (Get-Item -Path "env:$ApiKeyVar" -ErrorAction SilentlyContinue).Value
|
|
86
|
+
if ([string]::IsNullOrWhiteSpace($ApiKey)) {
|
|
87
|
+
$ApiKey = ""
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if ([string]::IsNullOrWhiteSpace($ApiKey)) {
|
|
91
|
+
Write-Host "No API key provided for provider '$OpenwikiProvider'. Daemon will run in collect-only mode." -ForegroundColor Yellow
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# Persist provider and model configuration
|
|
96
|
+
[System.Environment]::SetEnvironmentVariable("OPENWIKI_PROVIDER", $OpenwikiProvider, "User")
|
|
97
|
+
if (-not [string]::IsNullOrWhiteSpace($env:OPENWIKI_MODEL)) {
|
|
98
|
+
[System.Environment]::SetEnvironmentVariable("OPENWIKI_MODEL", $env:OPENWIKI_MODEL, "User")
|
|
99
|
+
}
|
|
100
|
+
if (-not [string]::IsNullOrWhiteSpace($env:OPENWIKI_BASE_URL)) {
|
|
101
|
+
[System.Environment]::SetEnvironmentVariable("OPENWIKI_BASE_URL", $env:OPENWIKI_BASE_URL, "User")
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
# Persist the appropriate API key
|
|
105
|
+
if (-not [string]::IsNullOrWhiteSpace($ApiKey) -and -not [string]::IsNullOrWhiteSpace($ApiKeyVar)) {
|
|
106
|
+
[System.Environment]::SetEnvironmentVariable($ApiKeyVar, $ApiKey, "User")
|
|
58
107
|
}
|
|
59
108
|
|
|
60
109
|
# 4. Ensure log directory
|
|
@@ -171,8 +220,12 @@ if ($Registered) {
|
|
|
171
220
|
Write-Host " -> Projects config: $DaemonLogDir\projects.json" -ForegroundColor Yellow
|
|
172
221
|
}
|
|
173
222
|
|
|
174
|
-
if (-not [string]::IsNullOrWhiteSpace($
|
|
175
|
-
|
|
223
|
+
if (-not [string]::IsNullOrWhiteSpace($ApiKey)) {
|
|
224
|
+
if (-not [string]::IsNullOrWhiteSpace($ApiKeyVar)) {
|
|
225
|
+
Write-Host " -> API key stored as the $ApiKeyVar user environment variable" -ForegroundColor Green
|
|
226
|
+
} else {
|
|
227
|
+
Write-Host " -> Provider configured: $OpenwikiProvider" -ForegroundColor Green
|
|
228
|
+
}
|
|
176
229
|
Write-Host " (not embedded in the task or the startup file)." -ForegroundColor Green
|
|
177
230
|
}
|
|
178
231
|
|
|
@@ -92,29 +92,65 @@ else
|
|
|
92
92
|
echo " -> google-genai installed; daemon will run under $DAEMON_PYTHON"
|
|
93
93
|
fi
|
|
94
94
|
|
|
95
|
-
# 3. Resolve API key
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
95
|
+
# 3. Resolve provider and API key
|
|
96
|
+
OPENWIKI_PROVIDER="${OPENWIKI_PROVIDER:-google}"
|
|
97
|
+
# set -u is active; a provider that needs no model override/base URL (the
|
|
98
|
+
# common case) never gets these exported, and the bare $OPENWIKI_MODEL /
|
|
99
|
+
# $OPENWIKI_BASE_URL reads inside write_launcher()'s subshell used to abort
|
|
100
|
+
# that subshell on "unbound variable" -- silently truncating the launcher
|
|
101
|
+
# before it reached the API key export or the final exec line.
|
|
102
|
+
OPENWIKI_MODEL="${OPENWIKI_MODEL:-}"
|
|
103
|
+
OPENWIKI_BASE_URL="${OPENWIKI_BASE_URL:-}"
|
|
104
|
+
|
|
105
|
+
# Map provider to its API key environment variable name
|
|
106
|
+
case "$OPENWIKI_PROVIDER" in
|
|
107
|
+
google) API_KEY_VAR="GEMINI_API_KEY" ;;
|
|
108
|
+
groq) API_KEY_VAR="GROQ_API_KEY" ;;
|
|
109
|
+
grok|xai) API_KEY_VAR="XAI_API_KEY" ;;
|
|
110
|
+
nvidia) API_KEY_VAR="NVIDIA_API_KEY" ;;
|
|
111
|
+
openrouter) API_KEY_VAR="OPENROUTER_API_KEY" ;;
|
|
112
|
+
openai) API_KEY_VAR="OPENAI_API_KEY" ;;
|
|
113
|
+
custom) API_KEY_VAR="OPENWIKI_API_KEY" ;;
|
|
114
|
+
ollama) API_KEY_VAR="" ;;
|
|
115
|
+
*) OPENWIKI_PROVIDER="google"; API_KEY_VAR="GEMINI_API_KEY" ;;
|
|
116
|
+
esac
|
|
117
|
+
|
|
118
|
+
# For Google provider, use the existing interactive flow with verification
|
|
119
|
+
if [ "$OPENWIKI_PROVIDER" = "google" ]; then
|
|
120
|
+
GEMINI_KEY="${GEMINI_API_KEY:-}"
|
|
121
|
+
if [ -z "$GEMINI_KEY" ]; then
|
|
122
|
+
echo ""
|
|
123
|
+
echo "GEMINI_API_KEY is not set in your environment."
|
|
124
|
+
read -rp "Enter your Gemini API key (or press Enter to skip): " GEMINI_KEY
|
|
125
|
+
fi
|
|
102
126
|
|
|
103
|
-
if [ -n "$GEMINI_KEY" ]; then
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
127
|
+
if [ -n "$GEMINI_KEY" ]; then
|
|
128
|
+
export GEMINI_API_KEY="$GEMINI_KEY"
|
|
129
|
+
echo "Verifying API key..."
|
|
130
|
+
VERIFY_OUTPUT=$("$DAEMON_PYTHON" "$SCRIPTS_DIR/verify_api_key.py" 2>&1)
|
|
131
|
+
VERIFY_CODE=$?
|
|
132
|
+
if [ $VERIFY_CODE -eq 0 ] && echo "$VERIFY_OUTPUT" | grep -q "VERIFIED_OK"; then
|
|
133
|
+
echo " -> API key verified successfully."
|
|
134
|
+
else
|
|
135
|
+
echo " -> WARNING: API key verification failed (with retry + TLS fallback)."
|
|
136
|
+
echo "$VERIFY_OUTPUT" | sed 's/^/ /'
|
|
137
|
+
echo " The daemon will run in collect-only mode until a valid key is set."
|
|
138
|
+
GEMINI_KEY=""
|
|
139
|
+
fi
|
|
110
140
|
else
|
|
111
|
-
echo "
|
|
112
|
-
echo "$VERIFY_OUTPUT" | sed 's/^/ /'
|
|
113
|
-
echo " The daemon will run in collect-only mode until a valid key is set."
|
|
114
|
-
GEMINI_KEY=""
|
|
141
|
+
echo "No API key provided. Daemon will run in collect-only mode."
|
|
115
142
|
fi
|
|
143
|
+
API_KEY="$GEMINI_KEY"
|
|
116
144
|
else
|
|
117
|
-
|
|
145
|
+
# For non-Google providers, skip verification and use the configured key
|
|
146
|
+
if [ -n "$API_KEY_VAR" ]; then
|
|
147
|
+
API_KEY="${!API_KEY_VAR:-}"
|
|
148
|
+
else
|
|
149
|
+
API_KEY=""
|
|
150
|
+
fi
|
|
151
|
+
if [ -z "$API_KEY" ]; then
|
|
152
|
+
echo "No API key provided for provider '$OPENWIKI_PROVIDER'. Daemon will run in collect-only mode."
|
|
153
|
+
fi
|
|
118
154
|
fi
|
|
119
155
|
|
|
120
156
|
# --- Helpers -------------------------------------------------------------
|
|
@@ -179,12 +215,29 @@ write_launcher() {
|
|
|
179
215
|
{
|
|
180
216
|
printf '#!/bin/sh\n'
|
|
181
217
|
printf '# Generated by install_daemon.sh - do not edit, re-run the installer.\n'
|
|
182
|
-
printf '# Holds the OpenWiki API
|
|
183
|
-
printf '# and the systemd unit. Mode 700 on purpose.\n'
|
|
218
|
+
printf '# Holds the OpenWiki provider config and API keys so they stay out of\n'
|
|
219
|
+
printf '# the LaunchAgent plist and the systemd unit. Mode 700 on purpose.\n'
|
|
184
220
|
printf 'HOME=%s; export HOME\n' "$(sq "$HOME")"
|
|
185
221
|
printf 'PATH=%s; export PATH\n' "$(sq "$path_value")"
|
|
186
|
-
if [ -n "$
|
|
187
|
-
printf '
|
|
222
|
+
if [ -n "$OPENWIKI_PROVIDER" ]; then
|
|
223
|
+
printf 'OPENWIKI_PROVIDER=%s; export OPENWIKI_PROVIDER\n' "$(sq "$OPENWIKI_PROVIDER")"
|
|
224
|
+
fi
|
|
225
|
+
if [ -n "$OPENWIKI_MODEL" ]; then
|
|
226
|
+
printf 'OPENWIKI_MODEL=%s; export OPENWIKI_MODEL\n' "$(sq "$OPENWIKI_MODEL")"
|
|
227
|
+
fi
|
|
228
|
+
if [ -n "$OPENWIKI_BASE_URL" ]; then
|
|
229
|
+
printf 'OPENWIKI_BASE_URL=%s; export OPENWIKI_BASE_URL\n' "$(sq "$OPENWIKI_BASE_URL")"
|
|
230
|
+
fi
|
|
231
|
+
if [ -n "$API_KEY" ]; then
|
|
232
|
+
case "$OPENWIKI_PROVIDER" in
|
|
233
|
+
google) printf 'GEMINI_API_KEY=%s; export GEMINI_API_KEY\n' "$(sq "$API_KEY")" ;;
|
|
234
|
+
groq) printf 'GROQ_API_KEY=%s; export GROQ_API_KEY\n' "$(sq "$API_KEY")" ;;
|
|
235
|
+
grok|xai) printf 'XAI_API_KEY=%s; export XAI_API_KEY\n' "$(sq "$API_KEY")" ;;
|
|
236
|
+
nvidia) printf 'NVIDIA_API_KEY=%s; export NVIDIA_API_KEY\n' "$(sq "$API_KEY")" ;;
|
|
237
|
+
openrouter) printf 'OPENROUTER_API_KEY=%s; export OPENROUTER_API_KEY\n' "$(sq "$API_KEY")" ;;
|
|
238
|
+
openai) printf 'OPENAI_API_KEY=%s; export OPENAI_API_KEY\n' "$(sq "$API_KEY")" ;;
|
|
239
|
+
custom) printf 'OPENWIKI_API_KEY=%s; export OPENWIKI_API_KEY\n' "$(sq "$API_KEY")" ;;
|
|
240
|
+
esac
|
|
188
241
|
fi
|
|
189
242
|
printf 'exec %s %s --one-shot\n' "$(sq "$python_bin")" "$(sq "$SCRIPT_PATH")"
|
|
190
243
|
} > "$LAUNCHER_PATH"
|
|
@@ -214,7 +267,7 @@ if [ "$OS" = "macos" ]; then
|
|
|
214
267
|
|
|
215
268
|
MACOS_PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
|
|
216
269
|
write_launcher "$DAEMON_PYTHON" "$MACOS_PATH"
|
|
217
|
-
echo " -> Launcher written to $LAUNCHER_PATH (mode 700; holds the API key
|
|
270
|
+
echo " -> Launcher written to $LAUNCHER_PATH (mode 700; holds the provider config and API key)."
|
|
218
271
|
|
|
219
272
|
cat <<EOF > "$PLIST_PATH"
|
|
220
273
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
@@ -272,7 +325,7 @@ elif [ "$OS" = "linux" ]; then
|
|
|
272
325
|
|
|
273
326
|
LINUX_PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
|
|
274
327
|
write_launcher "$DAEMON_PYTHON" "$LINUX_PATH"
|
|
275
|
-
echo " -> Launcher written to $LAUNCHER_PATH (mode 700; holds the API key
|
|
328
|
+
echo " -> Launcher written to $LAUNCHER_PATH (mode 700; holds the provider config and API key)."
|
|
276
329
|
|
|
277
330
|
cat > "$SYSTEMD_SERVICE" <<EOF
|
|
278
331
|
[Unit]
|
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const os = require('os');
|
|
4
|
-
const https = require('https');
|
|
5
|
-
const crypto = require('crypto');
|
|
6
|
-
const { execSync, spawn } = require('child_process');
|
|
7
|
-
|
|
8
|
-
const ISSUER = 'https://auth.awsbdb.rcentry.pro';
|
|
9
|
-
const TARBALL_URL = 'https://internal.awsbdb.rcentry.pro/aos-internal/aos-internal.tgz';
|
|
10
|
-
const CLIENT_ID = 'aos-installer';
|
|
11
|
-
const CONFIG_DIR = path.join(os.homedir(), '.agents');
|
|
12
|
-
const TOKEN_FILE = path.join(CONFIG_DIR, 'aos-internal.oauth.json');
|
|
13
|
-
|
|
14
|
-
function httpsGet(url) {
|
|
15
|
-
return new Promise((resolve, reject) => {
|
|
16
|
-
https.get(url, { timeout: 10000 }, (res) => {
|
|
17
|
-
let data = '';
|
|
18
|
-
res.on('data', chunk => data += chunk);
|
|
19
|
-
res.on('end', () => {
|
|
20
|
-
try {
|
|
21
|
-
resolve(JSON.parse(data));
|
|
22
|
-
} catch (e) {
|
|
23
|
-
reject(new Error(`Failed to parse response: ${e.message}`));
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
}).on('error', reject).on('timeout', function() {
|
|
27
|
-
this.destroy();
|
|
28
|
-
reject(new Error('Request timeout'));
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function httpsPost(url, body) {
|
|
34
|
-
return new Promise((resolve, reject) => {
|
|
35
|
-
const bodyStr = JSON.stringify(body);
|
|
36
|
-
const req = https.request(url, {
|
|
37
|
-
method: 'POST',
|
|
38
|
-
headers: {
|
|
39
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
|
40
|
-
'Content-Length': Buffer.byteLength(bodyStr)
|
|
41
|
-
},
|
|
42
|
-
timeout: 10000
|
|
43
|
-
}, (res) => {
|
|
44
|
-
let data = '';
|
|
45
|
-
res.on('data', chunk => data += chunk);
|
|
46
|
-
res.on('end', () => {
|
|
47
|
-
try {
|
|
48
|
-
resolve({ status: res.statusCode, body: JSON.parse(data) });
|
|
49
|
-
} catch (e) {
|
|
50
|
-
reject(new Error(`Failed to parse response: ${e.message}`));
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
req.on('error', reject);
|
|
55
|
-
req.on('timeout', function() {
|
|
56
|
-
this.destroy();
|
|
57
|
-
reject(new Error('Request timeout'));
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
const params = new URLSearchParams(body);
|
|
61
|
-
req.write(params.toString());
|
|
62
|
-
req.end();
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function httpsGetBinary(url, headers) {
|
|
67
|
-
return new Promise((resolve, reject) => {
|
|
68
|
-
const req = https.get(url, { headers, timeout: 30000 }, (res) => {
|
|
69
|
-
if (res.statusCode !== 200) {
|
|
70
|
-
reject(new Error(`HTTP ${res.statusCode}`));
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
const chunks = [];
|
|
74
|
-
res.on('data', chunk => chunks.push(chunk));
|
|
75
|
-
res.on('end', () => resolve(Buffer.concat(chunks)));
|
|
76
|
-
});
|
|
77
|
-
req.on('error', reject);
|
|
78
|
-
req.on('timeout', function() {
|
|
79
|
-
this.destroy();
|
|
80
|
-
reject(new Error('Request timeout'));
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function generatePKCE() {
|
|
86
|
-
const codeVerifier = crypto.randomBytes(32).toString('base64url');
|
|
87
|
-
const codeChallenge = crypto.createHash('sha256')
|
|
88
|
-
.update(codeVerifier)
|
|
89
|
-
.digest('base64url');
|
|
90
|
-
return { codeVerifier, codeChallenge };
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function tryOpenBrowser(verificationUri) {
|
|
94
|
-
const cmd = process.platform === 'darwin' ? 'open' :
|
|
95
|
-
process.platform === 'win32' ? 'start' : 'xdg-open';
|
|
96
|
-
try {
|
|
97
|
-
if (process.platform === 'win32') {
|
|
98
|
-
execSync(`start ${verificationUri}`, { stdio: 'ignore', shell: true });
|
|
99
|
-
} else {
|
|
100
|
-
execSync(`${cmd} "${verificationUri}"`, { stdio: 'ignore' });
|
|
101
|
-
}
|
|
102
|
-
} catch (e) {
|
|
103
|
-
// Browser open failed, but that's OK -- user can type the code manually
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function loadStoredToken() {
|
|
108
|
-
try {
|
|
109
|
-
if (!fs.existsSync(TOKEN_FILE)) return null;
|
|
110
|
-
const data = JSON.parse(fs.readFileSync(TOKEN_FILE, 'utf8'));
|
|
111
|
-
return data.refresh_token || null;
|
|
112
|
-
} catch (e) {
|
|
113
|
-
return null;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function saveToken(refreshToken) {
|
|
118
|
-
try {
|
|
119
|
-
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
120
|
-
fs.writeFileSync(TOKEN_FILE, JSON.stringify({ refresh_token: refreshToken }, null, 2), 'utf8');
|
|
121
|
-
fs.chmodSync(TOKEN_FILE, 0o600);
|
|
122
|
-
} catch (e) {
|
|
123
|
-
// If we can't save the token, continue anyway - the user will just re-auth next time
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
async function refreshAccessToken(refreshToken, discoveryResp) {
|
|
128
|
-
try {
|
|
129
|
-
const { codeVerifier } = generatePKCE();
|
|
130
|
-
const resp = await httpsPost(discoveryResp.token_endpoint, {
|
|
131
|
-
grant_type: 'refresh_token',
|
|
132
|
-
refresh_token: refreshToken,
|
|
133
|
-
client_id: CLIENT_ID,
|
|
134
|
-
code_verifier: codeVerifier
|
|
135
|
-
});
|
|
136
|
-
if (resp.body.access_token) {
|
|
137
|
-
if (resp.body.refresh_token) {
|
|
138
|
-
saveToken(resp.body.refresh_token);
|
|
139
|
-
}
|
|
140
|
-
return resp.body.access_token;
|
|
141
|
-
}
|
|
142
|
-
return null;
|
|
143
|
-
} catch (e) {
|
|
144
|
-
return null;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
async function pollForToken(discoveryResp, deviceCode, codeVerifier, interval, expiresIn) {
|
|
149
|
-
const deadline = Date.now() + (expiresIn * 1000);
|
|
150
|
-
let currentInterval = interval;
|
|
151
|
-
|
|
152
|
-
while (Date.now() < deadline) {
|
|
153
|
-
await new Promise(r => setTimeout(r, currentInterval * 1000));
|
|
154
|
-
|
|
155
|
-
try {
|
|
156
|
-
const resp = await httpsPost(discoveryResp.token_endpoint, {
|
|
157
|
-
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
158
|
-
device_code: deviceCode,
|
|
159
|
-
client_id: CLIENT_ID,
|
|
160
|
-
code_verifier: codeVerifier
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
const err = resp.body.error;
|
|
164
|
-
if (err === 'authorization_pending') {
|
|
165
|
-
continue;
|
|
166
|
-
} else if (err === 'slow_down') {
|
|
167
|
-
currentInterval += 5;
|
|
168
|
-
continue;
|
|
169
|
-
} else if (err === 'expired_token' || err === 'access_denied') {
|
|
170
|
-
return null;
|
|
171
|
-
} else if (resp.body.access_token) {
|
|
172
|
-
if (resp.body.refresh_token) {
|
|
173
|
-
saveToken(resp.body.refresh_token);
|
|
174
|
-
}
|
|
175
|
-
return resp.body.access_token;
|
|
176
|
-
}
|
|
177
|
-
} catch (e) {
|
|
178
|
-
// Network error, keep polling
|
|
179
|
-
continue;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
return null;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
async function tryFetchInternalAddon(log) {
|
|
186
|
-
try {
|
|
187
|
-
const discovery = await httpsGet(`${ISSUER}/.well-known/openid-configuration`);
|
|
188
|
-
|
|
189
|
-
if (!discovery.device_authorization_endpoint) {
|
|
190
|
-
log.warn('Internal add-on package not available — device_authorization_endpoint missing.');
|
|
191
|
-
return true;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
const scopes = discovery.scopes_supported || [];
|
|
195
|
-
if (!scopes.includes('authelia.bearer.authz')) {
|
|
196
|
-
log.warn('Internal add-on package not available — authelia.bearer.authz scope not supported.');
|
|
197
|
-
return true;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
let accessToken = null;
|
|
201
|
-
|
|
202
|
-
const storedRefresh = loadStoredToken();
|
|
203
|
-
if (storedRefresh) {
|
|
204
|
-
accessToken = await refreshAccessToken(storedRefresh, discovery);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if (!accessToken) {
|
|
208
|
-
const { codeVerifier, codeChallenge } = generatePKCE();
|
|
209
|
-
|
|
210
|
-
const deviceResp = await httpsPost(discovery.device_authorization_endpoint, {
|
|
211
|
-
client_id: CLIENT_ID,
|
|
212
|
-
scope: 'openid groups offline_access authelia.bearer.authz',
|
|
213
|
-
code_challenge: codeChallenge,
|
|
214
|
-
code_challenge_method: 'S256'
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
const deviceCode = deviceResp.body.device_code;
|
|
218
|
-
const userCode = deviceResp.body.user_code;
|
|
219
|
-
const verificationUri = deviceResp.body.verification_uri ||
|
|
220
|
-
deviceResp.body.verification_uri_complete;
|
|
221
|
-
const pollInterval = deviceResp.body.interval || 5;
|
|
222
|
-
const expiresIn = deviceResp.body.expires_in || 1800;
|
|
223
|
-
|
|
224
|
-
if (!deviceCode || !userCode || !verificationUri) {
|
|
225
|
-
log.warn('Internal add-on package not available — device flow not available.');
|
|
226
|
-
return true;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
log.message('');
|
|
230
|
-
log.message(' To authorize the internal add-on package:');
|
|
231
|
-
log.message(` Code: ${userCode}`);
|
|
232
|
-
log.message(` URL: ${verificationUri}`);
|
|
233
|
-
log.message('');
|
|
234
|
-
|
|
235
|
-
tryOpenBrowser(verificationUri);
|
|
236
|
-
|
|
237
|
-
accessToken = await pollForToken(discovery, deviceCode, codeVerifier, pollInterval, expiresIn);
|
|
238
|
-
if (!accessToken) {
|
|
239
|
-
log.warn('Internal add-on package not available — authorization timeout.');
|
|
240
|
-
return true;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
const tarballData = await httpsGetBinary(TARBALL_URL, {
|
|
245
|
-
'Authorization': `Bearer ${accessToken}`
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
const tempDir = path.join(CONFIG_DIR, '.tmp');
|
|
249
|
-
fs.mkdirSync(tempDir, { recursive: true });
|
|
250
|
-
const tempTarball = path.join(tempDir, 'aos-internal.tgz');
|
|
251
|
-
fs.writeFileSync(tempTarball, tarballData);
|
|
252
|
-
|
|
253
|
-
try {
|
|
254
|
-
const installDir = path.join(CONFIG_DIR, 'aos-internal');
|
|
255
|
-
fs.mkdirSync(installDir, { recursive: true });
|
|
256
|
-
execSync(`npm install "${tempTarball}"`, {
|
|
257
|
-
cwd: installDir,
|
|
258
|
-
stdio: 'pipe',
|
|
259
|
-
maxBuffer: 16 * 1024 * 1024
|
|
260
|
-
});
|
|
261
|
-
log.step('Internal add-on package installed');
|
|
262
|
-
return true;
|
|
263
|
-
} catch (e) {
|
|
264
|
-
log.warn('Internal add-on package not available — npm install failed.');
|
|
265
|
-
return true;
|
|
266
|
-
} finally {
|
|
267
|
-
try { fs.unlinkSync(tempTarball); } catch (e) {}
|
|
268
|
-
try { fs.rmdirSync(tempDir); } catch (e) {}
|
|
269
|
-
}
|
|
270
|
-
} catch (e) {
|
|
271
|
-
log.warn('Internal add-on package not available — continuing without it.');
|
|
272
|
-
return true;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
module.exports = { tryFetchInternalAddon };
|