@leg3ndy/otto-bridge 0.8.5 → 0.9.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.md +12 -6
- package/dist/runtime.js +14 -0
- package/dist/tool_catalog.js +193 -0
- package/dist/types.js +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,6 +13,8 @@ Para um passo a passo de instalacao, pareamento, uso, desconexao e desinstalacao
|
|
|
13
13
|
|
|
14
14
|
Para o estado atual da arquitetura, capacidades entregues, limitacoes e roadmap do Otto Bridge, veja [`leg3ndy-ai-backend/docs/OTTO_BRIDGE_ARCHITECTURE.md`](../leg3ndy-ai-backend/docs/OTTO_BRIDGE_ARCHITECTURE.md).
|
|
15
15
|
|
|
16
|
+
Para o corte de arquitetura do `0.9.0`, veja [`leg3ndy-ai-backend/docs/OTTO_BRIDGE_0_9_0_RELEASE.md`](../leg3ndy-ai-backend/docs/OTTO_BRIDGE_0_9_0_RELEASE.md).
|
|
17
|
+
|
|
16
18
|
## Distribuicao
|
|
17
19
|
|
|
18
20
|
Fluxo recomendado agora:
|
|
@@ -33,12 +35,14 @@ Enquanto o pacote nao estiver publicado, voce pode gerar um tarball local:
|
|
|
33
35
|
|
|
34
36
|
```bash
|
|
35
37
|
npm pack
|
|
36
|
-
npm install -g ./leg3ndy-otto-bridge-0.
|
|
38
|
+
npm install -g ./leg3ndy-otto-bridge-0.9.0.tgz
|
|
37
39
|
```
|
|
38
40
|
|
|
39
|
-
No `0.
|
|
41
|
+
No `0.9.0`, `playwright` segue como dependencia obrigatoria no `otto-bridge`. O primeiro `npm install -g @leg3ndy/otto-bridge` pode demorar mais porque instala o browser persistente usado pelo WhatsApp Web e pelos fluxos web em background do bridge.
|
|
42
|
+
|
|
43
|
+
No macOS, o `0.9.0` usa o provider `macos-helper`, um helper `WKWebView` sem Dock para o WhatsApp Web. O helper sobe com user-agent de Chrome moderno para evitar o bloqueio do WhatsApp ao detectar Safari/WebKit. O runtime antigo com Chromium/Playwright fica disponivel apenas como override explicito via `OTTO_BRIDGE_WHATSAPP_RUNTIME_PROVIDER=embedded-playwright`.
|
|
40
44
|
|
|
41
|
-
No
|
|
45
|
+
No nivel arquitetural, o `0.9.0` muda o papel do bridge: ele publica tools e resultados estruturados para o Otto, em vez de injetar resposta pronta como caminho principal do chat.
|
|
42
46
|
|
|
43
47
|
## Publicacao
|
|
44
48
|
|
|
@@ -108,7 +112,7 @@ otto-bridge run --executor clawd-cursor --clawd-url http://127.0.0.1:3847
|
|
|
108
112
|
|
|
109
113
|
### WhatsApp Web em background
|
|
110
114
|
|
|
111
|
-
Fluxo recomendado no `0.
|
|
115
|
+
Fluxo recomendado no `0.9.0`:
|
|
112
116
|
|
|
113
117
|
```bash
|
|
114
118
|
otto-bridge extensions --install whatsappweb
|
|
@@ -118,13 +122,13 @@ otto-bridge extensions --status whatsappweb
|
|
|
118
122
|
|
|
119
123
|
O setup agora abre o login do WhatsApp Web no helper/background browser do proprio bridge. Depois do QR code, o Otto usa a sessao local em background, sem depender de aba visivel no Safari.
|
|
120
124
|
|
|
121
|
-
Contrato do `0.
|
|
125
|
+
Contrato do `0.9.0`:
|
|
122
126
|
|
|
123
127
|
- `otto-bridge extensions --setup whatsappweb`: autentica a sessao uma vez
|
|
124
128
|
- `otto-bridge run`: mantem o browser persistente do WhatsApp vivo em background enquanto o runtime estiver ativo, sem depender de uma aba aberta no Safari
|
|
125
129
|
- ao parar o `otto-bridge run`: o browser em background e desligado, mas a sessao local fica lembrada para o proximo boot
|
|
126
130
|
|
|
127
|
-
## Handoff rapido do 0.
|
|
131
|
+
## Handoff rapido do 0.9.0
|
|
128
132
|
|
|
129
133
|
Ja fechado no codigo:
|
|
130
134
|
|
|
@@ -132,6 +136,8 @@ Ja fechado no codigo:
|
|
|
132
136
|
- user-agent do helper ajustado para evitar bloqueio do WhatsApp por detecao de Safari/WebKit
|
|
133
137
|
- resultado final dos `device_job` agora e persistido como contexto mais forte para o proximo turno do Otto
|
|
134
138
|
- prompt bridge-aware no chat normal para ajudar o Otto a responder com base no que realmente aconteceu no device
|
|
139
|
+
- runtime local agora publica `local_tools` para o Otto/backend saberem exatamente o que o device consegue fazer
|
|
140
|
+
- o caminho principal do bridge usa `summary`/`narration_context` no lugar de resposta automatica pronta
|
|
135
141
|
|
|
136
142
|
Ainda precisa reteste em campo:
|
|
137
143
|
|
package/dist/runtime.js
CHANGED
|
@@ -5,6 +5,7 @@ import { NativeMacOSJobExecutor } from "./executors/native_macos.js";
|
|
|
5
5
|
import { JobCancelledError } from "./executors/shared.js";
|
|
6
6
|
import { isManagedBridgeExtensionSlug, loadManagedBridgeExtensionState, } from "./extensions.js";
|
|
7
7
|
import { LocalAutomationRuntime } from "./local_automations.js";
|
|
8
|
+
import { buildLocalToolCatalog } from "./tool_catalog.js";
|
|
8
9
|
function delay(ms) {
|
|
9
10
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
10
11
|
}
|
|
@@ -89,6 +90,7 @@ export class BridgeRuntime {
|
|
|
89
90
|
const metadata = {
|
|
90
91
|
...(this.config.metadata || {}),
|
|
91
92
|
installed_extensions: this.config.installedExtensions,
|
|
93
|
+
executor_type: this.config.executor.type,
|
|
92
94
|
};
|
|
93
95
|
const managedExtensions = {};
|
|
94
96
|
const connectedMessageApps = new Set();
|
|
@@ -125,9 +127,21 @@ export class BridgeRuntime {
|
|
|
125
127
|
if (Object.keys(managedExtensions).length > 0) {
|
|
126
128
|
metadata.managed_extensions = managedExtensions;
|
|
127
129
|
}
|
|
130
|
+
else {
|
|
131
|
+
delete metadata.managed_extensions;
|
|
132
|
+
}
|
|
128
133
|
if (connectedMessageApps.size > 0) {
|
|
129
134
|
metadata.connected_message_apps = Array.from(connectedMessageApps);
|
|
130
135
|
}
|
|
136
|
+
else {
|
|
137
|
+
delete metadata.connected_message_apps;
|
|
138
|
+
}
|
|
139
|
+
const toolCatalog = buildLocalToolCatalog({
|
|
140
|
+
executorType: this.config.executor.type,
|
|
141
|
+
connectedMessageApps: metadata.connected_message_apps,
|
|
142
|
+
});
|
|
143
|
+
metadata.local_tools_version = toolCatalog.version;
|
|
144
|
+
metadata.local_tools = toolCatalog.tools;
|
|
131
145
|
return metadata;
|
|
132
146
|
}
|
|
133
147
|
async sendHello(socket) {
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { BRIDGE_LOCAL_TOOLS_VERSION, } from "./types.js";
|
|
2
|
+
const NATIVE_MACOS_BASE_TOOLS = [
|
|
3
|
+
{
|
|
4
|
+
id: "desktop.apps",
|
|
5
|
+
title: "Abrir e focar apps",
|
|
6
|
+
description: "Abre aplicativos locais e traz uma janela para frente no macOS.",
|
|
7
|
+
category: "desktop",
|
|
8
|
+
mode: "control",
|
|
9
|
+
action_types: ["open_app", "focus_app"],
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
id: "browser.navigation",
|
|
13
|
+
title: "Abrir links e destinos web",
|
|
14
|
+
description: "Abre URLs e pesquisas locais no navegador.",
|
|
15
|
+
category: "browser",
|
|
16
|
+
mode: "control",
|
|
17
|
+
action_types: ["open_url"],
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: "content.notes",
|
|
21
|
+
title: "Criar notas e texto",
|
|
22
|
+
description: "Cria notas, digita texto e executa atalhos locais de escrita.",
|
|
23
|
+
category: "content",
|
|
24
|
+
mode: "write",
|
|
25
|
+
action_types: ["create_note", "type_text", "press_shortcut"],
|
|
26
|
+
requires_confirmation: true,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: "desktop.capture",
|
|
30
|
+
title: "Captura de tela",
|
|
31
|
+
description: "Tira screenshot local do macOS.",
|
|
32
|
+
category: "desktop",
|
|
33
|
+
mode: "observe",
|
|
34
|
+
action_types: ["take_screenshot"],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: "browser.context",
|
|
38
|
+
title: "Leitura do navegador",
|
|
39
|
+
description: "Le a pagina frontal e coleta contexto da aba atual do navegador.",
|
|
40
|
+
category: "browser",
|
|
41
|
+
mode: "observe",
|
|
42
|
+
action_types: ["read_frontmost_page", "browser_context"],
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: "system.apps",
|
|
46
|
+
title: "Status de apps",
|
|
47
|
+
description: "Checa app em foco, apps abertos e processos pesados.",
|
|
48
|
+
category: "system",
|
|
49
|
+
mode: "observe",
|
|
50
|
+
action_types: ["app_status"],
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: "filesystem.overview",
|
|
54
|
+
title: "Inspecao de arquivos e pastas",
|
|
55
|
+
description: "Inspeciona caminhos locais, lista itens e conta arquivos.",
|
|
56
|
+
category: "filesystem",
|
|
57
|
+
mode: "observe",
|
|
58
|
+
action_types: ["filesystem_inspect", "list_files", "count_files"],
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: "filesystem.read",
|
|
62
|
+
title: "Leitura de arquivo",
|
|
63
|
+
description: "Le arquivos de texto quando o caminho esta claro.",
|
|
64
|
+
category: "filesystem",
|
|
65
|
+
mode: "observe",
|
|
66
|
+
action_types: ["read_file"],
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: "system.health",
|
|
70
|
+
title: "Status do Mac",
|
|
71
|
+
description: "Coleta CPU, memoria, disco, bateria e processos de topo.",
|
|
72
|
+
category: "system",
|
|
73
|
+
mode: "observe",
|
|
74
|
+
action_types: ["system_status"],
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: "shell.inspect",
|
|
78
|
+
title: "Shell local",
|
|
79
|
+
description: "Roda comandos locais de consulta e diagnostico.",
|
|
80
|
+
category: "shell",
|
|
81
|
+
mode: "control",
|
|
82
|
+
action_types: ["run_shell"],
|
|
83
|
+
requires_confirmation: true,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
id: "desktop.audio",
|
|
87
|
+
title: "Controle de volume",
|
|
88
|
+
description: "Ajusta o volume do macOS.",
|
|
89
|
+
category: "desktop",
|
|
90
|
+
mode: "control",
|
|
91
|
+
action_types: ["set_volume"],
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: "desktop.scroll",
|
|
95
|
+
title: "Scroll da tela",
|
|
96
|
+
description: "Rola a view ativa para cima ou para baixo.",
|
|
97
|
+
category: "desktop",
|
|
98
|
+
mode: "control",
|
|
99
|
+
action_types: ["scroll_view"],
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: "visual.click",
|
|
103
|
+
title: "Clique visual guiado",
|
|
104
|
+
description: "Procura um alvo simples na tela e clica nele.",
|
|
105
|
+
category: "visual",
|
|
106
|
+
mode: "control",
|
|
107
|
+
action_types: ["click_visual_target"],
|
|
108
|
+
requires_confirmation: true,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
id: "visual.drag",
|
|
112
|
+
title: "Arraste visual guiado",
|
|
113
|
+
description: "Arrasta um alvo visivel para outro alvo visivel.",
|
|
114
|
+
category: "visual",
|
|
115
|
+
mode: "control",
|
|
116
|
+
action_types: ["drag_visual_target"],
|
|
117
|
+
requires_confirmation: true,
|
|
118
|
+
},
|
|
119
|
+
];
|
|
120
|
+
const MOCK_TOOLS = [
|
|
121
|
+
{
|
|
122
|
+
id: "mock.runtime",
|
|
123
|
+
title: "Execucao mock",
|
|
124
|
+
description: "Simula a execucao local para testes sem efeitos reais no dispositivo.",
|
|
125
|
+
category: "desktop",
|
|
126
|
+
mode: "control",
|
|
127
|
+
action_types: [],
|
|
128
|
+
notes: "Os resultados sao sinteticos e servem apenas para desenvolvimento.",
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
const CLAWD_CURSOR_TOOLS = [
|
|
132
|
+
{
|
|
133
|
+
id: "clawd.cursor.task",
|
|
134
|
+
title: "Tarefa aberta no executor",
|
|
135
|
+
description: "Delegacao geral para o runtime Clawd Cursor executar uma tarefa no computador.",
|
|
136
|
+
category: "desktop",
|
|
137
|
+
mode: "control",
|
|
138
|
+
action_types: [],
|
|
139
|
+
requires_confirmation: true,
|
|
140
|
+
},
|
|
141
|
+
];
|
|
142
|
+
function hasConnectedMessageApp(apps, target) {
|
|
143
|
+
return apps.some((item) => item === target);
|
|
144
|
+
}
|
|
145
|
+
function buildNativeMessagingTools(connectedMessageApps) {
|
|
146
|
+
const tools = [];
|
|
147
|
+
if (hasConnectedMessageApp(connectedMessageApps, "whatsapp")) {
|
|
148
|
+
tools.push({
|
|
149
|
+
id: "messaging.whatsapp.read",
|
|
150
|
+
title: "Leitura de WhatsApp",
|
|
151
|
+
description: "Abre uma conversa no WhatsApp Web e le as mensagens visiveis.",
|
|
152
|
+
category: "messaging",
|
|
153
|
+
mode: "observe",
|
|
154
|
+
action_types: ["whatsapp_read_chat"],
|
|
155
|
+
}, {
|
|
156
|
+
id: "messaging.whatsapp.send",
|
|
157
|
+
title: "Envio de WhatsApp",
|
|
158
|
+
description: "Abre a conversa certa e envia mensagem no WhatsApp Web.",
|
|
159
|
+
category: "messaging",
|
|
160
|
+
mode: "write",
|
|
161
|
+
action_types: ["whatsapp_send_message"],
|
|
162
|
+
requires_confirmation: true,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
return tools;
|
|
166
|
+
}
|
|
167
|
+
export function buildLocalToolCatalog(context) {
|
|
168
|
+
const connectedMessageApps = Array.from(new Set((context.connectedMessageApps || [])
|
|
169
|
+
.map((item) => String(item || "").trim().toLowerCase())
|
|
170
|
+
.filter(Boolean)));
|
|
171
|
+
if (context.executorType === "native-macos") {
|
|
172
|
+
return {
|
|
173
|
+
version: BRIDGE_LOCAL_TOOLS_VERSION,
|
|
174
|
+
executor_type: context.executorType,
|
|
175
|
+
tools: [
|
|
176
|
+
...NATIVE_MACOS_BASE_TOOLS,
|
|
177
|
+
...buildNativeMessagingTools(connectedMessageApps),
|
|
178
|
+
],
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
if (context.executorType === "clawd-cursor") {
|
|
182
|
+
return {
|
|
183
|
+
version: BRIDGE_LOCAL_TOOLS_VERSION,
|
|
184
|
+
executor_type: context.executorType,
|
|
185
|
+
tools: CLAWD_CURSOR_TOOLS,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
version: BRIDGE_LOCAL_TOOLS_VERSION,
|
|
190
|
+
executor_type: context.executorType,
|
|
191
|
+
tools: MOCK_TOOLS,
|
|
192
|
+
};
|
|
193
|
+
}
|
package/dist/types.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const BRIDGE_CONFIG_VERSION = 1;
|
|
2
|
-
export const BRIDGE_VERSION = "0.
|
|
2
|
+
export const BRIDGE_VERSION = "0.9.0";
|
|
3
3
|
export const BRIDGE_PACKAGE_NAME = "@leg3ndy/otto-bridge";
|
|
4
4
|
export const DEFAULT_API_BASE_URL = "http://localhost:8000";
|
|
5
5
|
export const DEFAULT_POLL_INTERVAL_MS = 3000;
|
|
@@ -10,3 +10,4 @@ export const DEFAULT_RECONNECT_MAX_DELAY_MS = 15000;
|
|
|
10
10
|
export const DEFAULT_EXECUTOR_TYPE = "mock";
|
|
11
11
|
export const DEFAULT_CLAWD_CURSOR_BASE_URL = "http://127.0.0.1:3847";
|
|
12
12
|
export const DEFAULT_CLAWD_CURSOR_POLL_INTERVAL_MS = 1500;
|
|
13
|
+
export const BRIDGE_LOCAL_TOOLS_VERSION = 1;
|