@leg3ndy/otto-bridge 1.1.5 → 1.1.6
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 +55 -17
- 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.6`, veja [`leg3ndy-ai-backend/docs/otto-bridge/releases/OTTO_BRIDGE_1_1_6_PATCH.md`](../leg3ndy-ai-backend/docs/otto-bridge/releases/OTTO_BRIDGE_1_1_6_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.6.tgz
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
Na linha `1.1.
|
|
44
|
+
Na linha `1.1.6`, `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.6` 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.6` 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 endurece o `Otto Console` para manter o scrollback real sem vazar separadores do rodape e deduplicar chunks de stream sobrepostos.
|
|
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.6`:
|
|
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.6`:
|
|
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.6
|
|
190
190
|
|
|
191
191
|
Ja fechado no codigo:
|
|
192
192
|
|
package/dist/cli_terminal.js
CHANGED
|
@@ -552,7 +552,8 @@ class ConsoleScreenRenderer {
|
|
|
552
552
|
slashSuggestions = [];
|
|
553
553
|
selectedSuggestionIndex = 0;
|
|
554
554
|
renderedOnce = false;
|
|
555
|
-
|
|
555
|
+
renderedLineCount = 0;
|
|
556
|
+
renderedTopRow = 0;
|
|
556
557
|
constructor(modelMode, approvalMode, headerFactory = () => []) {
|
|
557
558
|
this.modelMode = modelMode;
|
|
558
559
|
this.approvalMode = approvalMode;
|
|
@@ -581,6 +582,8 @@ class ConsoleScreenRenderer {
|
|
|
581
582
|
clearTranscript() {
|
|
582
583
|
this.liveEntries.splice(0, this.liveEntries.length);
|
|
583
584
|
this.renderedOnce = false;
|
|
585
|
+
this.renderedLineCount = 0;
|
|
586
|
+
this.renderedTopRow = 0;
|
|
584
587
|
clearScreen();
|
|
585
588
|
output.write(this.headerFactory().join("\n"));
|
|
586
589
|
output.write("\n\n");
|
|
@@ -682,19 +685,20 @@ class ConsoleScreenRenderer {
|
|
|
682
685
|
getRenderWidth() {
|
|
683
686
|
return Math.max(48, Number(output.columns || 96));
|
|
684
687
|
}
|
|
688
|
+
getRenderHeight() {
|
|
689
|
+
return Math.max(10, Number(output.rows || 24));
|
|
690
|
+
}
|
|
685
691
|
clearRenderBlock() {
|
|
686
692
|
if (!this.renderedOnce) {
|
|
687
693
|
return;
|
|
688
694
|
}
|
|
689
695
|
output.write("\u001b[?25l");
|
|
690
|
-
cursorTo(output, 0);
|
|
691
|
-
if (this.renderedCursorLineIndex > 0) {
|
|
692
|
-
moveCursor(output, 0, -this.renderedCursorLineIndex);
|
|
693
|
-
}
|
|
696
|
+
cursorTo(output, 0, this.renderedTopRow);
|
|
694
697
|
clearScreenDown(output);
|
|
695
698
|
output.write("\u001b[?25h");
|
|
696
699
|
this.renderedOnce = false;
|
|
697
|
-
this.
|
|
700
|
+
this.renderedLineCount = 0;
|
|
701
|
+
this.renderedTopRow = 0;
|
|
698
702
|
}
|
|
699
703
|
printLinesAbove(lines) {
|
|
700
704
|
if (!this.active) {
|
|
@@ -716,13 +720,13 @@ class ConsoleScreenRenderer {
|
|
|
716
720
|
}
|
|
717
721
|
const enabled = supportsAnsi();
|
|
718
722
|
const width = this.getRenderWidth();
|
|
723
|
+
const height = this.getRenderHeight();
|
|
719
724
|
const separator = style("─".repeat(width), ANSI.brandBlue, enabled);
|
|
720
725
|
const composer = renderConsoleComposerLines(this.draftValue, width, enabled);
|
|
721
726
|
const suggestionLines = buildConsoleSlashSuggestionLines(this.slashSuggestions, this.selectedSuggestionIndex, width, enabled);
|
|
722
727
|
const usageTokens = Math.min(estimateConsoleContextTokens(this.conversationMessages, this.draftValue), getCliModelContextWindowTokens(this.modelMode));
|
|
723
728
|
const liveLines = this.liveEntries.flatMap((entry) => this.buildEntryLines(entry, width));
|
|
724
|
-
const
|
|
725
|
-
...liveLines,
|
|
729
|
+
const footerLines = [
|
|
726
730
|
separator,
|
|
727
731
|
...composer.renderedLines,
|
|
728
732
|
...suggestionLines,
|
|
@@ -730,17 +734,24 @@ class ConsoleScreenRenderer {
|
|
|
730
734
|
buildConsoleFooterStatusLine(width, this.modelMode, usageTokens, enabled),
|
|
731
735
|
buildConsoleFooterApprovalLine(this.approvalMode, enabled, this.approvalStatusSuffix),
|
|
732
736
|
];
|
|
737
|
+
const maxVisibleLiveLines = Math.max(0, height - footerLines.length);
|
|
738
|
+
const visibleLiveLines = maxVisibleLiveLines > 0
|
|
739
|
+
? liveLines.slice(-maxVisibleLiveLines)
|
|
740
|
+
: [];
|
|
741
|
+
const blockLines = [
|
|
742
|
+
...visibleLiveLines,
|
|
743
|
+
...footerLines,
|
|
744
|
+
];
|
|
745
|
+
const topRow = Math.max(0, height - blockLines.length);
|
|
733
746
|
this.clearRenderBlock();
|
|
734
747
|
output.write("\u001b[?25l");
|
|
748
|
+
cursorTo(output, 0, topRow);
|
|
735
749
|
output.write(blockLines.join("\n"));
|
|
736
750
|
this.renderedOnce = true;
|
|
737
|
-
this.
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
moveCursor(output, 0, -linesBelowCursor);
|
|
742
|
-
}
|
|
743
|
-
cursorTo(output, Math.min(width - 1, CONSOLE_COMPOSER_CURSOR_COLUMN + composer.cursorColumn));
|
|
751
|
+
this.renderedLineCount = blockLines.length;
|
|
752
|
+
this.renderedTopRow = topRow;
|
|
753
|
+
const composerRow = topRow + visibleLiveLines.length + 1 + composer.cursorLineIndex;
|
|
754
|
+
cursorTo(output, Math.min(width - 1, CONSOLE_COMPOSER_CURSOR_COLUMN + composer.cursorColumn), composerRow);
|
|
744
755
|
output.write("\u001b[?25h");
|
|
745
756
|
}
|
|
746
757
|
}
|
|
@@ -1455,6 +1466,29 @@ export function tryConsumeControlSequence(buffer) {
|
|
|
1455
1466
|
}
|
|
1456
1467
|
return null;
|
|
1457
1468
|
}
|
|
1469
|
+
export function resolveConsoleStreamDelta(previousText, incomingChunk) {
|
|
1470
|
+
const previous = previousText || "";
|
|
1471
|
+
const incoming = incomingChunk || "";
|
|
1472
|
+
if (!incoming) {
|
|
1473
|
+
return "";
|
|
1474
|
+
}
|
|
1475
|
+
if (!previous) {
|
|
1476
|
+
return incoming;
|
|
1477
|
+
}
|
|
1478
|
+
if (incoming === previous || previous.endsWith(incoming)) {
|
|
1479
|
+
return "";
|
|
1480
|
+
}
|
|
1481
|
+
if (incoming.startsWith(previous)) {
|
|
1482
|
+
return incoming.slice(previous.length);
|
|
1483
|
+
}
|
|
1484
|
+
const maxOverlap = Math.min(previous.length, incoming.length);
|
|
1485
|
+
for (let overlap = maxOverlap; overlap > 0; overlap -= 1) {
|
|
1486
|
+
if (previous.slice(-overlap) === incoming.slice(0, overlap)) {
|
|
1487
|
+
return incoming.slice(overlap);
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
return incoming;
|
|
1491
|
+
}
|
|
1458
1492
|
class ConsoleInputController {
|
|
1459
1493
|
rl;
|
|
1460
1494
|
ui;
|
|
@@ -2484,6 +2518,7 @@ async function runOttoConsole(rl, config, runtimeSession, options) {
|
|
|
2484
2518
|
conversation.push({ role: "user", content: normalizedPrompt });
|
|
2485
2519
|
renderConversationState();
|
|
2486
2520
|
let streamedAssistant = "";
|
|
2521
|
+
let streamedReasoning = "";
|
|
2487
2522
|
let assistantEntryId = null;
|
|
2488
2523
|
let assistantPrefixPrinted = false;
|
|
2489
2524
|
let reasoningPrefixPrinted = false;
|
|
@@ -2513,7 +2548,7 @@ async function runOttoConsole(rl, config, runtimeSession, options) {
|
|
|
2513
2548
|
throw new Error(errorMessage);
|
|
2514
2549
|
}
|
|
2515
2550
|
const reasoningChunk = typeof event.content === "string" && eventType === "reasoning"
|
|
2516
|
-
? event.content
|
|
2551
|
+
? resolveConsoleStreamDelta(streamedReasoning, event.content)
|
|
2517
2552
|
: "";
|
|
2518
2553
|
if (reasoningChunk) {
|
|
2519
2554
|
if (!reasoningPrefixPrinted) {
|
|
@@ -2529,9 +2564,12 @@ async function runOttoConsole(rl, config, runtimeSession, options) {
|
|
|
2529
2564
|
else {
|
|
2530
2565
|
output.write(style(reasoningChunk, ANSI.slateItalic, supportsAnsi()));
|
|
2531
2566
|
}
|
|
2567
|
+
streamedReasoning += reasoningChunk;
|
|
2532
2568
|
return;
|
|
2533
2569
|
}
|
|
2534
|
-
const contentChunk = typeof event.content === "string"
|
|
2570
|
+
const contentChunk = typeof event.content === "string"
|
|
2571
|
+
? resolveConsoleStreamDelta(streamedAssistant, event.content)
|
|
2572
|
+
: "";
|
|
2535
2573
|
if (!contentChunk) {
|
|
2536
2574
|
return;
|
|
2537
2575
|
}
|
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.6";
|
|
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.6");
|
|
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"], {
|