@leg3ndy/otto-bridge 1.1.3 → 1.1.4
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 +8 -8
- package/dist/cli_terminal.js +58 -23
- package/dist/types.js +1 -1
- package/package.json +1 -1
- package/scripts/postinstall.mjs +1 -1
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ Para o estado atual da arquitetura, capacidades entregues, limitacoes e roadmap
|
|
|
15
15
|
|
|
16
16
|
Para o corte de arquitetura do `0.9.0`, veja [`leg3ndy-ai-backend/docs/otto-bridge/releases/OTTO_BRIDGE_0_9_0_RELEASE.md`](../leg3ndy-ai-backend/docs/otto-bridge/releases/OTTO_BRIDGE_0_9_0_RELEASE.md).
|
|
17
17
|
|
|
18
|
-
Para o patch atual `1.1.
|
|
18
|
+
Para o patch atual `1.1.4`, veja [`leg3ndy-ai-backend/docs/otto-bridge/releases/OTTO_BRIDGE_1_1_4_PATCH.md`](../leg3ndy-ai-backend/docs/otto-bridge/releases/OTTO_BRIDGE_1_1_4_PATCH.md). Para o corte funcional da linha `1.1.0`, veja [`leg3ndy-ai-backend/docs/otto-bridge/releases/OTTO_BRIDGE_1_1_0_RELEASE.md`](../leg3ndy-ai-backend/docs/otto-bridge/releases/OTTO_BRIDGE_1_1_0_RELEASE.md).
|
|
19
19
|
|
|
20
20
|
## Distribuicao
|
|
21
21
|
|
|
@@ -38,14 +38,14 @@ Enquanto o pacote nao estiver publicado, voce pode gerar um tarball local:
|
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
40
|
npm pack
|
|
41
|
-
npm install -g ./leg3ndy-otto-bridge-1.1.
|
|
41
|
+
npm install -g ./leg3ndy-otto-bridge-1.1.4.tgz
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
Na linha `1.1.
|
|
44
|
+
Na linha `1.1.4`, `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.
|
|
45
45
|
|
|
46
|
-
No macOS, a linha `1.1.
|
|
46
|
+
No macOS, a linha `1.1.4` 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`.
|
|
47
47
|
|
|
48
|
-
No nivel arquitetural, o `0.9.0` marcou a mudanca de papel do bridge: ele publica tools e resultados estruturados para o Otto, em vez de injetar resposta pronta como caminho principal do chat. O `1.0.0` oficializou isso como runtime agentico; o `1.1.
|
|
48
|
+
No nivel arquitetural, o `0.9.0` marcou a mudanca de papel do bridge: ele publica tools e resultados estruturados para o Otto, em vez de injetar resposta pronta como caminho principal do chat. O `1.0.0` oficializou isso como runtime agentico; o `1.1.4` mantem a camada workspace-first com rail de coding, trust/policy por workspace, source control first-class, working set persistido e grounding remoto por repositório, enquanto corrige a regressao do `Otto Console` e volta ao renderer fixo com header no topo, transcript acima do composer, menu com setas e palette de comandos ao digitar `/`.
|
|
49
49
|
|
|
50
50
|
## Publicacao
|
|
51
51
|
|
|
@@ -170,7 +170,7 @@ Esse comando abre um shell local interativo para instalar extensoes, rodar coman
|
|
|
170
170
|
|
|
171
171
|
### WhatsApp Web em background
|
|
172
172
|
|
|
173
|
-
Fluxo recomendado na linha `1.1.
|
|
173
|
+
Fluxo recomendado na linha `1.1.4`:
|
|
174
174
|
|
|
175
175
|
```bash
|
|
176
176
|
otto-bridge extensions --install whatsappweb
|
|
@@ -180,13 +180,13 @@ otto-bridge extensions --status whatsappweb
|
|
|
180
180
|
|
|
181
181
|
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.
|
|
182
182
|
|
|
183
|
-
Contrato da linha `1.1.
|
|
183
|
+
Contrato da linha `1.1.4`:
|
|
184
184
|
|
|
185
185
|
- `otto-bridge extensions --setup whatsappweb`: autentica a sessao uma vez
|
|
186
186
|
- `otto-bridge`: mantem o browser persistente do WhatsApp vivo em background enquanto o runtime do hub estiver ativo, sem depender de uma aba aberta no Safari
|
|
187
187
|
- ao fechar o `otto-bridge`: o browser em background e desligado, mas a sessao local fica lembrada para o proximo boot
|
|
188
188
|
|
|
189
|
-
## Handoff rapido da linha 1.1.
|
|
189
|
+
## Handoff rapido da linha 1.1.4
|
|
190
190
|
|
|
191
191
|
Ja fechado no codigo:
|
|
192
192
|
|
package/dist/cli_terminal.js
CHANGED
|
@@ -509,6 +509,21 @@ function buildConsoleFooterApprovalLine(mode, enabled, statusSuffix) {
|
|
|
509
509
|
const hint = statusSuffix || "Shift+Tab para alternar";
|
|
510
510
|
return style(`${state.label} (${hint})`, state.tone === "warning" ? ANSI.red : state.tone === "primary" ? ANSI.amber : ANSI.slate, enabled);
|
|
511
511
|
}
|
|
512
|
+
function buildConsoleSlashSuggestionLines(suggestions, selectedSuggestionIndex, width, enabled) {
|
|
513
|
+
if (!suggestions.length) {
|
|
514
|
+
return [];
|
|
515
|
+
}
|
|
516
|
+
const suggestionWidth = Math.max(24, width - 4);
|
|
517
|
+
return suggestions.map((item, index) => {
|
|
518
|
+
const selected = index === selectedSuggestionIndex;
|
|
519
|
+
const prefix = selected
|
|
520
|
+
? style("›", `${ANSI.bold}${ANSI.brandBlue}`, enabled)
|
|
521
|
+
: style(" ", ANSI.slate, enabled);
|
|
522
|
+
const command = style(item.command, selected ? `${ANSI.bold}${ANSI.white}` : ANSI.brandBlue, enabled);
|
|
523
|
+
const description = style(truncate(item.description, Math.max(12, suggestionWidth - item.command.length - 4)), selected ? ANSI.white : ANSI.slate, enabled);
|
|
524
|
+
return `${prefix} ${command} ${description}`;
|
|
525
|
+
});
|
|
526
|
+
}
|
|
512
527
|
function styleTranscriptPrefix(text, tone, enabled) {
|
|
513
528
|
if (!enabled || !text) {
|
|
514
529
|
return text;
|
|
@@ -534,6 +549,8 @@ class ConsoleScreenRenderer {
|
|
|
534
549
|
draftValue = "";
|
|
535
550
|
conversationMessages = [];
|
|
536
551
|
approvalStatusSuffix = null;
|
|
552
|
+
slashSuggestions = [];
|
|
553
|
+
selectedSuggestionIndex = 0;
|
|
537
554
|
usingAlternateBuffer = false;
|
|
538
555
|
constructor(modelMode, approvalMode, headerFactory = () => []) {
|
|
539
556
|
this.modelMode = modelMode;
|
|
@@ -593,6 +610,23 @@ class ConsoleScreenRenderer {
|
|
|
593
610
|
this.draftValue = value;
|
|
594
611
|
this.render();
|
|
595
612
|
}
|
|
613
|
+
setSlashSuggestions(suggestions, selectedSuggestionIndex = 0) {
|
|
614
|
+
this.slashSuggestions = [...suggestions];
|
|
615
|
+
this.selectedSuggestionIndex = Math.max(0, Math.min(selectedSuggestionIndex, Math.max(0, suggestions.length - 1)));
|
|
616
|
+
this.render();
|
|
617
|
+
}
|
|
618
|
+
setComposerState(value, suggestions, selectedSuggestionIndex = 0) {
|
|
619
|
+
this.draftValue = value;
|
|
620
|
+
this.slashSuggestions = [...suggestions];
|
|
621
|
+
this.selectedSuggestionIndex = Math.max(0, Math.min(selectedSuggestionIndex, Math.max(0, suggestions.length - 1)));
|
|
622
|
+
this.render();
|
|
623
|
+
}
|
|
624
|
+
resetComposer() {
|
|
625
|
+
this.draftValue = "";
|
|
626
|
+
this.slashSuggestions = [];
|
|
627
|
+
this.selectedSuggestionIndex = 0;
|
|
628
|
+
this.render();
|
|
629
|
+
}
|
|
596
630
|
setConversationMessages(messages) {
|
|
597
631
|
this.conversationMessages = [...messages];
|
|
598
632
|
this.render();
|
|
@@ -641,10 +675,12 @@ class ConsoleScreenRenderer {
|
|
|
641
675
|
const headerLines = this.headerFactory();
|
|
642
676
|
const separator = style("─".repeat(width), ANSI.brandBlue, enabled);
|
|
643
677
|
const composer = renderConsoleComposerLines(this.draftValue, width, enabled);
|
|
678
|
+
const suggestionLines = buildConsoleSlashSuggestionLines(this.slashSuggestions, this.selectedSuggestionIndex, width, enabled);
|
|
644
679
|
const usageTokens = Math.min(estimateConsoleContextTokens(this.conversationMessages, this.draftValue), getCliModelContextWindowTokens(this.modelMode));
|
|
645
680
|
const footerLines = [
|
|
646
681
|
separator,
|
|
647
682
|
...composer.renderedLines,
|
|
683
|
+
...suggestionLines,
|
|
648
684
|
separator,
|
|
649
685
|
buildConsoleFooterStatusLine(width, this.modelMode, usageTokens, enabled),
|
|
650
686
|
buildConsoleFooterApprovalLine(this.approvalMode, enabled, this.approvalStatusSuffix),
|
|
@@ -664,8 +700,19 @@ class ConsoleScreenRenderer {
|
|
|
664
700
|
output.write("\u001b[?25h");
|
|
665
701
|
}
|
|
666
702
|
}
|
|
667
|
-
function createConsoleScreenRenderer(
|
|
668
|
-
|
|
703
|
+
export function createConsoleScreenRenderer(modelMode, approvalMode, runtimeSession, options) {
|
|
704
|
+
const canRender = (options?.ansiEnabled ?? supportsAnsi())
|
|
705
|
+
&& (options?.inputIsTTY ?? Boolean(input.isTTY))
|
|
706
|
+
&& (options?.outputIsTTY ?? Boolean(output.isTTY))
|
|
707
|
+
&& (options?.hasRawMode ?? typeof input.setRawMode === "function");
|
|
708
|
+
if (!canRender) {
|
|
709
|
+
return null;
|
|
710
|
+
}
|
|
711
|
+
const renderer = new ConsoleScreenRenderer(modelMode, approvalMode, () => buildConsoleHeaderLines(runtimeSession));
|
|
712
|
+
if (options?.autoActivate ?? true) {
|
|
713
|
+
renderer.activate();
|
|
714
|
+
}
|
|
715
|
+
return renderer;
|
|
669
716
|
}
|
|
670
717
|
export function resolveCliModelMode(value) {
|
|
671
718
|
const normalized = normalizeText(value).toLowerCase();
|
|
@@ -1401,27 +1448,11 @@ async function askConsoleInput(rl, options) {
|
|
|
1401
1448
|
input.setRawMode(false);
|
|
1402
1449
|
input.pause();
|
|
1403
1450
|
rl.resume();
|
|
1404
|
-
ui?.
|
|
1405
|
-
};
|
|
1406
|
-
const renderSuggestionLines = (width) => {
|
|
1407
|
-
const suggestions = getVisibleSuggestions();
|
|
1408
|
-
if (!suggestions.length) {
|
|
1409
|
-
return [];
|
|
1410
|
-
}
|
|
1411
|
-
const suggestionWidth = Math.max(24, width - 4);
|
|
1412
|
-
return suggestions.map((item, index) => {
|
|
1413
|
-
const selected = index === selectedSuggestionIndex;
|
|
1414
|
-
const prefix = selected
|
|
1415
|
-
? style("›", `${ANSI.bold}${ANSI.brandBlue}`, enabled)
|
|
1416
|
-
: style(" ", ANSI.slate, enabled);
|
|
1417
|
-
const command = style(item.command, selected ? `${ANSI.bold}${ANSI.white}` : ANSI.brandBlue, enabled);
|
|
1418
|
-
const description = style(truncate(item.description, Math.max(12, suggestionWidth - item.command.length - 4)), selected ? ANSI.white : ANSI.slate, enabled);
|
|
1419
|
-
return `${prefix} ${command} ${description}`;
|
|
1420
|
-
});
|
|
1451
|
+
ui?.resetComposer();
|
|
1421
1452
|
};
|
|
1422
1453
|
const renderPromptBlock = () => {
|
|
1423
1454
|
if (ui) {
|
|
1424
|
-
ui.
|
|
1455
|
+
ui.setComposerState(value, getVisibleSuggestions(), selectedSuggestionIndex);
|
|
1425
1456
|
return;
|
|
1426
1457
|
}
|
|
1427
1458
|
const width = getPromptWidth();
|
|
@@ -1429,7 +1460,7 @@ async function askConsoleInput(rl, options) {
|
|
|
1429
1460
|
const modelMode = getModelMode();
|
|
1430
1461
|
const approvalMode = getApprovalMode();
|
|
1431
1462
|
const usageTokens = Math.min(estimateConsoleContextTokens(getConversationMessages(), value), getCliModelContextWindowTokens(modelMode));
|
|
1432
|
-
const suggestionLines =
|
|
1463
|
+
const suggestionLines = buildConsoleSlashSuggestionLines(getVisibleSuggestions(), selectedSuggestionIndex, width, enabled);
|
|
1433
1464
|
const blockLines = [
|
|
1434
1465
|
style("─".repeat(width), ANSI.brandBlue, enabled),
|
|
1435
1466
|
...composer.renderedLines,
|
|
@@ -1530,7 +1561,9 @@ async function askConsoleInput(rl, options) {
|
|
|
1530
1561
|
continue;
|
|
1531
1562
|
}
|
|
1532
1563
|
cleanup();
|
|
1533
|
-
|
|
1564
|
+
if (!ui) {
|
|
1565
|
+
output.write("\n");
|
|
1566
|
+
}
|
|
1534
1567
|
resolve(normalizeText(value));
|
|
1535
1568
|
return;
|
|
1536
1569
|
}
|
|
@@ -1548,7 +1581,9 @@ async function askConsoleInput(rl, options) {
|
|
|
1548
1581
|
renderPromptBlock();
|
|
1549
1582
|
}
|
|
1550
1583
|
};
|
|
1551
|
-
|
|
1584
|
+
if (!ui) {
|
|
1585
|
+
output.on("resize", renderPromptBlock);
|
|
1586
|
+
}
|
|
1552
1587
|
renderPromptBlock();
|
|
1553
1588
|
input.on("data", onData);
|
|
1554
1589
|
});
|
package/dist/types.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const BRIDGE_CONFIG_VERSION = 1;
|
|
2
|
-
export const BRIDGE_VERSION = "1.1.
|
|
2
|
+
export const BRIDGE_VERSION = "1.1.4";
|
|
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;
|
package/package.json
CHANGED
package/scripts/postinstall.mjs
CHANGED
|
@@ -24,7 +24,7 @@ if (!existsSync(mainPath)) {
|
|
|
24
24
|
process.exit(0);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
console.log("\n[otto-bridge] Welcome to OTTOAI 1.1.
|
|
27
|
+
console.log("\n[otto-bridge] Welcome to OTTOAI 1.1.4");
|
|
28
28
|
console.log("[otto-bridge] Vamos iniciar o setup interativo do bridge.\n");
|
|
29
29
|
|
|
30
30
|
const result = spawnSync(process.execPath, [mainPath, "setup", "--postinstall"], {
|