agentgui 1.0.943 → 1.0.944
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/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
## [Unreleased] -
|
|
1
|
+
## [Unreleased] - live e2e chat verified + composer caret fix + ccsniff memory cap
|
|
2
|
+
|
|
3
|
+
- verified the full GUI chat round-trip end-to-end in a real browser: compose -> WS chat.sendMessage -> claude-code -> streaming_progress -> transcript renders the streamed reply (not just the runner harness).
|
|
4
|
+
- site/app/js/app.js: composer onInput re-renders only on the empty<->non-empty draft transition (the only change that toggles the send button), not on every keystroke. Why: a synchronous re-render per character fought the caret on the controlled textarea.
|
|
5
|
+
- vendored anentrypoint-design DS rebuilt: ChatComposer reads the live textarea value on send and syncs the controlled value into the DOM only when it differs, so a mid-type re-render no longer resets the caret or drops keystrokes. Why: DS override belongs in the kit; the composer is shared.
|
|
6
|
+
- ccsniff (sibling repo, pushed): bounded the in-memory history store (event cap + eviction + per-event text cap) and bounded loadOnce to read newest events first up to the cap. Why: the store grew unbounded to 6GB+ (OOM) and parsed the entire JSONL backlog at load (~2.4GB transient peak); heap now settles ~47MB and load peak ~570MB.
|
|
2
7
|
|
|
3
8
|
- lib/agent-discovery.js + lib/claude-runner-agents.js + lib/agent-descriptors.js: added `agy` (Antigravity) as a direct-protocol CLI agent — `agy --print "<prompt>" --dangerously-skip-permissions [--continue]`, plain-text parseOutput, no model picker. Completes the four flagship orchestration targets (Claude Code, OpenCode, Kilo, Antigravity). Why: the GUI could not drive Antigravity at all.
|
|
4
9
|
- lib/claude-runner.js + lib/claude-runner-direct.js: SECURITY — the direct runner now spawns a resolved binary with `shell:false`. Previously `shell:true` on Windows concatenated argv unescaped, so a prompt containing `&`/`|`/`>`/backticks executed as shell commands (verified injection). Why: arbitrary command execution from chat input.
|
package/package.json
CHANGED
package/site/app/js/app.js
CHANGED
|
@@ -434,7 +434,16 @@ function chatMain() {
|
|
|
434
434
|
value: state.chat.draft,
|
|
435
435
|
disabled: !canSend(),
|
|
436
436
|
placeholder,
|
|
437
|
-
|
|
437
|
+
// The DS textarea is controlled and reads its live DOM value on send, so we
|
|
438
|
+
// do NOT re-render on every keystroke (that fights the cursor and is wasteful).
|
|
439
|
+
// Re-render only when the draft crosses empty<->non-empty, since that is the
|
|
440
|
+
// only transition that changes the send button's disabled state.
|
|
441
|
+
onInput: (v) => {
|
|
442
|
+
const was = !!(state.chat.draft && state.chat.draft.trim());
|
|
443
|
+
const now = !!(v && v.trim());
|
|
444
|
+
state.chat.draft = v;
|
|
445
|
+
if (was !== now) render();
|
|
446
|
+
},
|
|
438
447
|
onSend: (v) => { state.chat.draft = v; sendChat(); },
|
|
439
448
|
});
|
|
440
449
|
|
|
@@ -518,14 +518,43 @@
|
|
|
518
518
|
|
|
519
519
|
.ds-247420 .app-topbar {
|
|
520
520
|
position: sticky; top: 0; z-index: var(--z-header);
|
|
521
|
-
display:
|
|
521
|
+
display: flex; flex-wrap: wrap;
|
|
522
522
|
align-items: center; gap: var(--space-4);
|
|
523
523
|
min-height: var(--app-topbar-h);
|
|
524
524
|
padding: 10px var(--pad-x);
|
|
525
525
|
background: color-mix(in oklab, var(--bg) 88%, transparent);
|
|
526
526
|
backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
|
|
527
527
|
}
|
|
528
|
-
|
|
528
|
+
|
|
529
|
+
/* Merged chrome: when AppShell gets both a topbar and a crumb it wraps them
|
|
530
|
+
in .app-chrome and they share ONE sticky band instead of stacking as two
|
|
531
|
+
bars. The breadcrumb provides the left identity (it already begins with the
|
|
532
|
+
brand), so the topbar's standalone brand is hidden to avoid showing the name
|
|
533
|
+
twice; nav and the crumb's right slot sit together on the right. */
|
|
534
|
+
.ds-247420 .app-chrome {
|
|
535
|
+
position: sticky; top: 0; z-index: var(--z-header);
|
|
536
|
+
display: flex; flex-wrap: wrap; align-items: center;
|
|
537
|
+
gap: var(--space-2) var(--space-4);
|
|
538
|
+
padding: 8px var(--pad-x);
|
|
539
|
+
background: color-mix(in oklab, var(--bg) 88%, transparent);
|
|
540
|
+
backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
|
|
541
|
+
}
|
|
542
|
+
.ds-247420 .app-chrome > .app-topbar,
|
|
543
|
+
.ds-247420 .app-chrome > .app-crumb {
|
|
544
|
+
position: static; background: none; backdrop-filter: none;
|
|
545
|
+
-webkit-backdrop-filter: none; padding: 0; min-height: 0;
|
|
546
|
+
flex: 1 1 auto;
|
|
547
|
+
}
|
|
548
|
+
.ds-247420 .app-chrome > .app-crumb { order: 1; flex: 1 1 auto; }
|
|
549
|
+
.ds-247420 .app-chrome > .app-topbar { order: 2; flex: 0 0 auto; }
|
|
550
|
+
.ds-247420 .app-chrome > .app-topbar > .brand { display: none; }
|
|
551
|
+
.ds-247420 .app-chrome > .app-topbar > nav { margin-left: 0; }
|
|
552
|
+
.ds-247420 .app-chrome > .app-crumb > .crumb-right { margin-left: auto; }
|
|
553
|
+
.ds-247420 .app-topbar > .brand { flex: 0 0 auto; }
|
|
554
|
+
.ds-247420 .app-topbar > .app-search { flex: 1 1 auto; }
|
|
555
|
+
.ds-247420 .app-topbar > nav { margin-left: auto; }
|
|
556
|
+
.ds-247420 .app-topbar nav { display: flex; gap: 4px; font-size: var(--fs-sm); flex-wrap: wrap; }
|
|
557
|
+
.ds-247420 .app-topbar nav a { flex: 0 0 auto; }
|
|
529
558
|
.ds-247420 .app-topbar nav a {
|
|
530
559
|
color: var(--fg-2);
|
|
531
560
|
padding: 12px 14px;
|
|
@@ -1083,25 +1112,21 @@
|
|
|
1083
1112
|
/* App Layout: single-column + drawer is handled once in the ≤900px block;
|
|
1084
1113
|
no need to re-declare grid-template-columns here (was a redundant !important). */
|
|
1085
1114
|
|
|
1086
|
-
/* Topbar Navigation
|
|
1115
|
+
/* Topbar Navigation: stack the nav onto its own full-width row below the
|
|
1116
|
+
brand and let it scroll horizontally. The brand stays on the first row;
|
|
1117
|
+
nav wraps to a second row at 100% width (flex-wrap on .app-topbar). */
|
|
1087
1118
|
.ds-247420 .app-topbar {
|
|
1088
|
-
grid-template-columns: 1fr auto;
|
|
1089
1119
|
gap: var(--space-2); padding: 12px var(--space-3);
|
|
1090
1120
|
}
|
|
1091
|
-
.ds-247420 .app-topbar nav
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
}
|
|
1095
|
-
/* Keep primary nav reachable on small screens (apps without a sidebar have
|
|
1096
|
-
no other entry point). Compact it and let it scroll horizontally rather
|
|
1097
|
-
than hiding it entirely. */
|
|
1098
|
-
.ds-247420 .app-topbar nav {
|
|
1099
|
-
display: flex; gap: 2px;
|
|
1121
|
+
.ds-247420 .app-topbar > nav {
|
|
1122
|
+
flex: 1 1 100%; margin-left: 0; order: 3;
|
|
1123
|
+
display: flex; gap: 2px; flex-wrap: nowrap;
|
|
1100
1124
|
overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
|
|
1101
|
-
max-width: 60vw;
|
|
1102
1125
|
}
|
|
1103
1126
|
.ds-247420 .app-topbar nav::-webkit-scrollbar { display: none; }
|
|
1104
|
-
.ds-247420 .app-topbar nav a {
|
|
1127
|
+
.ds-247420 .app-topbar nav a {
|
|
1128
|
+
flex: 0 0 auto; padding: 10px 12px; min-height: 44px; white-space: nowrap;
|
|
1129
|
+
}
|
|
1105
1130
|
.ds-247420 .brand { font-size: var(--fs-tiny); font-weight: 600; }
|
|
1106
1131
|
|
|
1107
1132
|
/* Search */
|