From ce36dcde52d4609048e2db6459c4d1fb394d567c Mon Sep 17 00:00:00 2001 From: Levi Neely <141506390+lneely@users.noreply.github.com> Date: Wed, 5 Aug 2026 18:53:30 +0200 Subject: [PATCH] Update KDE README and remove D-Bus dependencies - Rewrite README.md with accurate 9P-based architecture - Remove all D-Bus dependencies: - Update dolphin/ollie-ask to use ollie-9p rdwr generate - Update kate/ollie_ghost.cpp to use ollie-9p rdwr complete - Remove QDBusInterface from ollie_ghost.h - Fix OllieGhostProvider constructor in ollie_kate.cpp - Remove D-Bus comments from gui/main.cpp and kate/ollie_kate.cpp - Remove QtDBus from CMakeLists.txt (KF5 and KF6) - Delete D-Bus test scripts test-e2e.sh and test-peers.sh - Clarify no system tray component exists - Update build/install instructions with just commands --- CMakeLists.txt | 4 +- README.md | 167 ++++++++++++++++++++++++++++--------------- dolphin/ollie-ask | 12 +--- gui/main.cpp | 2 +- kate/ollie_ghost.cpp | 53 ++++++++------ kate/ollie_ghost.h | 8 +-- kate/ollie_kate.cpp | 8 +-- test-e2e.sh | 85 ---------------------- test-peers.sh | 56 --------------- 9 files changed, 154 insertions(+), 241 deletions(-) delete mode 100755 test-e2e.sh delete mode 100755 test-peers.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 290fa2a..f86e0ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ endif() if(OLLIE_KF5) # --- Qt5 / KF5 --- - find_package(Qt5 REQUIRED COMPONENTS Core Concurrent DBus Widgets Quick Qml QuickControls2 Network) + find_package(Qt5 REQUIRED COMPONENTS Core Concurrent Widgets Quick Qml QuickControls2 Network) # Override KDE_INSTALL_PLUGINDIR so kcoreaddons_add_plugin installs under # CMAKE_INSTALL_PREFIX (e.g. ~/.local/lib/qt5/plugins), not the system dir. @@ -138,7 +138,6 @@ else() target_link_libraries(krunner_ollie KF6::Runner Qt6::Core - Qt6::DBus Qt6::Widgets ) @@ -159,7 +158,6 @@ else() KF6::TextEditor KF6::SyntaxHighlighting Qt6::Core - Qt6::DBus Qt6::Widgets $ENV{HOME}/.local/lib/libollie9p.so ) diff --git a/README.md b/README.md index 19d5f75..9bf66a7 100644 --- a/README.md +++ b/README.md @@ -1,78 +1,97 @@ # ollie-kde -KDE-native integration for [ollie](../README.md) — thin KDE clients (system -tray, Plasmoid, KRunner, Kate plugin, Dolphin menus) that talk to the -`org.ollie.SessionManager` D-Bus interface. +KDE-native integration for [ollie](../README.md) — thin KDE clients (GUI application, KRunner plugin, Kate plugin, Dolphin menus, Plasmoid) that connect directly to the Ollie 9P filesystem. ## Architecture ``` ┌──────────────────────────────────────────────────────────────┐ │ Plasma Desktop │ -│ System Tray │ KRunner │ Plasmoid │ Kate Plugin │ Dolphin │ +│ GUI App │ KRunner │ Kate Plugin │ Dolphin │ Plasmoid │ └──────────────────────────┬───────────────────────────────────┘ - │ D-Bus (org.ollie.SessionManager) + │ 9P filesystem (ollie-9p transport) │ ┌────────────────┴────────────────┐ │ │ ┌─────────┴──────────┐ ┌───────────┴──────────────────┐ -│ ollied (../dbus) │ │ olliesrv -nodbus=false │ -│ Pure D-Bus daemon│ │ (../9p, embedded adapter) │ -│ Go │ godbus │ │ Go │ 9P + D-Bus │ +│ olliesrv (../9p) │ │ ollie-9p (../cmd/ollie-9p) │ +│ 9P server │ │ 9P client + transport │ +│ Go │ lib9p │ │ Go │ lib9p │ └────────────────────┘ └──────────────────────────────┘ ``` -Two backends provide the D-Bus interface — pick one: +All KDE components use the 9P filesystem directly via `ollie-9p` subprocess calls. **No D-Bus dependency** — the architecture is fully 9P-based. -- **ollied** (`../dbus/`) — standalone D-Bus daemon, pure Go, no 9P. Lighter weight. -- **olliesrv** (`../9p/`) — the full 9P server with an embedded D-Bus adapter (enabled by default; disable with `-nodbus`). +## Components -Both register the same `org.ollie.SessionManager` bus name. They cannot run -side by side — choose one. KDE components here are pure D-Bus clients, -lightweight, stateless, and independently restartable. +- **ollie-gui** — Main Qt/QML GUI application with session management and chat interface +- **krunner_ollie.so** — KRunner plugin for quick prompts and session management +- **ollie_kate.so** — Kate plugin with integrated chat panel and editor integration +- **Plasmoid** — Desktop widget for session monitoring and quick access +- **Dolphin service menus** — Right-click actions for files and directories + +**Note**: No system tray component exists (old documentation was incorrect). ## Dependencies -- Qt 6 (Core, DBus, Widgets, Quick) or Qt 5 (Core, DBus, Widgets, Quick, Qml) -- KDE Frameworks 6 (StatusNotifierItem, Runner, TextEditor, CoreAddons, Config) - or KDE Frameworks 5 (Notifications, Runner, TextEditor, CoreAddons, Config, Plasma) +- Qt 6 (Core, Widgets, Quick, QuickControls2) or Qt 5 (Core, Widgets, Quick, Qml, QuickControls2) +- KDE Frameworks 6 (Runner, CoreAddons, Config, TextEditor, SyntaxHighlighting) or KF5 equivalents - Plasma 6 or Plasma 5 (for Plasmoid) - ECM (Extra CMake Modules) +- libollie9p.so (from `../lib9p/`) KF6/Qt6 is the default. To build against KF5/Qt5: - ```sh -make kf5 +just kde-kf5 ``` ## Build ```sh -make # builds tray + KRunner + Kate + Plasmoid via CMake +just kde # builds all components (KF6) +just kde-kf5 # builds all components (KF5) ``` Outputs: -- `build-cmake/ollie-tray` — system tray icon +- `build-cmake/ollie-gui` — main GUI application - `build-cmake/lib/kf6/krunner/krunner_ollie.so` — KRunner plugin - `build-cmake/lib/kf6/ktexteditor/ollie_kate.so` — Kate plugin -- `build-cmake/org/ollie/private/` — Plasmoid QML plugin +- `build-cmake/lib/libollie-plasmoid-plugin.so` — Plasmoid QML plugin +- `build-cmake/org/ollie/private/ollie-plasmoid-pluginplugin.so` — Plasmoid plugin loader ## Install ```sh -sudo make install # all KDE components (KF6) -sudo make kf5-install # all KDE components (KF5) - -# Individual: -make krunner-install -make dolphin-install -make plasmoid-install +just install-kde # installs all KDE components (KF6) +just install-kde-kf5 # installs all KDE components (KF5) ``` -The D-Bus daemon is installed separately — either `ollied` from `../dbus/` or use `olliesrv` from `../9p/` (which includes D-Bus by default). +The installation: +- Installs binaries to `~/.local/bin/` +- Installs plugins to `~/.local/lib64/qt6/plugins/` (KF6) or `~/.local/lib/qt5/plugins/` (KF5) +- Installs Dolphin service menus to `~/.local/share/kio/servicemenus/` +- Installs desktop entry to `~/.local/share/applications/` +- Installs icon to `~/.local/share/icons/hicolor/scalable/apps/` +- Sets up environment script in `~/.config/plasma-workspace/env/` + +**Note**: Restart Plasma (`plasmashell --replace` or log out/in) to pick up new plugins. ## Usage +### GUI Application (`ollie-gui`) + +Launch from application menu or terminal: +```sh +ollie-gui +``` + +Features: +- Session list with state indicators (idle, thinking, tool call) +- Live chat view with auto-scroll +- Inline prompt input +- Real-time updates via 9P polling +- Theme support (light/dark/system) + ### KRunner - `ollie ` — one-shot generation via `Generate` (no session created); shows result in a popup @@ -87,52 +106,86 @@ Right-click any file or directory: ### Kate -Enable the "Ollie" plugin in Settings → Configure Kate → Plugins. Panel appears -on the right with: +Enable the "Ollie" plugin in Settings → Configure Kate → Plugins. Panel appears on the right with: + - Session indicator + CWD label - **New** — create session in project/file directory - **Ask File** — send current file path for description - **Explain** — send selected text for explanation - Prompt input for free-form messages - Live-streaming chat view +- Editor integration (inline annotations, code block application, ghost text completion) ### Plasmoid Add the "Ollie" widget to your panel or desktop: -- Session list with state indicators (○ idle, ● thinking, ⚡ tool call) +- Session list with state indicators - Live chat view with auto-scroll - Inline prompt input -- Real-time updates via D-Bus signals - -### System Tray - -- Tooltip: session count -- Status: passive (no sessions), active (sessions idle), attention (agent working) -- Right-click: New Session, Sessions submenu (kill each), Stop All, Quit +- Real-time updates via 9P polling ## File Layout ``` ollie-kde/ -├── Makefile # CMake orchestration -├── CMakeLists.txt -├── tray/ -│ ├── main.cpp -│ └── ollie_tray.h/cpp # KStatusNotifierItem +├── justfile # Build orchestration +├── CMakeLists.txt # Main CMake configuration +├── CMakeLists-kf5.txt # KF5-specific overrides +├── gui/ +│ ├── main.cpp # GUI application entry +│ ├── main.qml # QML interface +│ ├── ollie9pclient.h/cpp # 9P client for GUI +│ ├── lib9pclient.h/cpp # Shared 9P client library +│ ├── chatblockmodel.h/cpp # Chat data model +│ ├── thememanager.h/cpp # Theme management +│ ├── streamfsm.h/cpp # Streaming state machine +│ ├── ninepconnection.h/cpp # 9P connection management +│ └── org.ollie.gui.desktop # Desktop entry ├── krunner/ -│ ├── metadata.json -│ └── ollie_runner.h/cpp # KRunner plugin +│ ├── metadata.json # Plugin metadata +│ └── ollie_runner.h/cpp # KRunner plugin (9P-based) ├── kate/ -│ ├── metadata.json -│ └── ollie_kate.h/cpp # KTextEditor plugin +│ ├── metadata.json # Plugin metadata +│ ├── ollie_kate.h/cpp # Kate plugin (9P-based) +│ ├── ollie_ghost.h/cpp # Ghost text provider (9P-based) +│ ├── chat_renderer.h/cpp # Chat rendering engine +│ ├── ktexteditor_utils.h # Editor utilities +│ └── diffparams.h # Diff viewer parameters ├── plasmoid/ -│ ├── metadata.json -│ ├── contents/ui/main.qml -│ └── plugin/ -│ └── olliedbusclient.h/cpp # QML singleton (D-Bus client) +│ ├── plugin/ +│ │ └── olliedbusclient.h/cpp # QML singleton (9P client - misnamed) +│ └── contents/ui/main.qml # Plasmoid QML interface ├── dolphin/ -│ ├── ollie-actions.desktop # Service menu entries -│ ├── ollie-ask # One-shot helper script -│ └── ollie-session-here # Session creation helper -└── test-e2e.sh # End-to-end test script +│ ├── ollie-actions.desktop # Service menu entries (KF6) +│ ├── ollie-actions-kf5.desktop # Service menu entries (KF5) +│ ├── ollie-ask # One-shot helper script (9P-based) +│ └── ollie-session-here # Session creation helper (9P-based) +├── 99-ollie.sh # Environment script (KF6) +├── 99-ollie-kf5.sh # Environment script (KF5) +└── test-peers.sh # Peer connection tests ``` + +## Development Notes + +- **All components use `ollie-9p` for 9P transport** — no D-Bus dependencies +- The Kate plugin includes sophisticated editor integration with ghost text, inline annotations, and diff viewing +- The GUI application uses Qt Quick for a modern, responsive interface +- Build system supports both KF6/Qt6 and KF5/Qt5 via CMake option `OLLIE_KF5` +- Installation is user-local (`~/.local/`) by default, no system-wide installation needed + +## Troubleshooting + +**Plugins not appearing after installation:** +- Run `kbuildsycoca6` (KF6) or `kbuildsycoca5` (KF5) to rebuild system cache +- Restart Plasma: `plasmashell --replace` or log out/in + +**"ollie-9p not found" errors:** +- Ensure `ollie-9p` is in your PATH or build/install the main Ollie project first + +**Kate plugin crashes:** +- Check that `libollie9p.so` is installed in `~/.local/lib/` +- Verify Kate is using the same Qt version as the plugin (Qt5 vs Qt6) + +**Dolphin actions not working:** +- Ensure `ollie-ask` and `ollie-session-here` are installed in `~/.local/bin/` +- Check that the service menu desktop files are in `~/.local/share/kio/servicemenus/` \ No newline at end of file diff --git a/dolphin/ollie-ask b/dolphin/ollie-ask index 810f5b2..da02a4c 100755 --- a/dolphin/ollie-ask +++ b/dolphin/ollie-ask @@ -6,17 +6,11 @@ TARGET="$1" PREFIX="${2:-Describe and explain this file:}" PROMPT="$PREFIX $TARGET" -SERVICE="org.ollie.SessionManager" -OBJ="/org/ollie/SessionManager" -IFACE="org.ollie.SessionManager" - -# Use Generate one-shot — no session needed -RESULT=$(gdbus call --session --dest $SERVICE --object-path $OBJ \ - --method $IFACE.Generate "$PROMPT" "" "" "" 2>/dev/null | \ - sed "s/^('//; s/')$//; s/\\\\n/\n/g") +# Use Generate one-shot via 9P +RESULT=$(echo "$PROMPT" | ollie-9p rdwr generate 2>/dev/null) if [ -z "$RESULT" ]; then - notify-send "Ollie" "No response (is olliesrv or ollied running?)" + notify-send "Ollie" "No response (is olliesrv running?)" exit 1 fi diff --git a/gui/main.cpp b/gui/main.cpp index 517aa7c..d416fef 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -1,5 +1,5 @@ // ollie-gui-9p: minimal Qt GUI using 9P for all communication. -// No D-Bus dependency. Uses ollie-9p subprocess for 9P transport. +// Uses ollie-9p subprocess for 9P transport. #include #include #include diff --git a/kate/ollie_ghost.cpp b/kate/ollie_ghost.cpp index 3d655d1..ba07f9e 100644 --- a/kate/ollie_ghost.cpp +++ b/kate/ollie_ghost.cpp @@ -8,18 +8,13 @@ #include #endif -#include -#include -#include -#include #include #include #include #include - -static const char *DBUS_SERVICE = "org.ollie.SessionManager"; -static const char *DBUS_PATH = "/org/ollie/SessionManager"; -static const char *DBUS_IFACE = "org.ollie.SessionManager"; +#include +#include +#include // === GhostOverlay === @@ -85,10 +80,9 @@ void GhostOverlay::paintEvent(QPaintEvent *event) // === OllieGhostProvider === -OllieGhostProvider::OllieGhostProvider(KTextEditor::View *view, QDBusInterface *iface, OllieKatePlugin *plugin, QObject *parent) +OllieGhostProvider::OllieGhostProvider(KTextEditor::View *view, OllieKatePlugin *plugin, QObject *parent) : KTextEditor::InlineNoteProvider() // note: KDE's ctor takes no parent arg , m_view(view) - , m_iface(iface) , m_plugin(plugin) , m_debounce(new QTimer(this)) { @@ -317,22 +311,39 @@ void OllieGhostProvider::requestCompletion() context += QStringLiteral("model=") + model + QStringLiteral("\n"); } - QDBusMessage msg = QDBusMessage::createMethodCall( - DBUS_SERVICE, DBUS_PATH, DBUS_IFACE, "Complete"); - msg << cwd << filePath << prefix << suffix << context; + // Build JSON request for ollie-9p rdwr complete + QJsonObject request; + request["file"] = filePath; + request["prefix"] = prefix; + request["suffix"] = suffix; + if (!context.isEmpty()) { + request["context"] = context; + } - QDBusPendingCall pending = QDBusConnection::sessionBus().asyncCall(msg, 15000); - auto *watcher = new QDBusPendingCallWatcher(pending, this); - connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *w) { - w->deleteLater(); + QJsonDocument docJson(request); + QString jsonStr = QString::fromUtf8(docJson.toJson(QJsonDocument::Compact)); + + // Run ollie-9p rdwr complete + QProcess *process = new QProcess(this); + process->setProgram("ollie-9p"); + process->setArguments({"rdwr", "complete"}); + + connect(process, QOverload::of(&QProcess::finished), + this, [this, process](int exitCode, QProcess::ExitStatus exitStatus) { + process->deleteLater(); m_requesting = false; - QDBusPendingReply reply = *w; - if (reply.isError()) { + if (exitStatus != QProcess::NormalExit || exitCode != 0) { return; } - onCompletionReply(reply.value()); + + QString result = QString::fromUtf8(process->readAllStandardOutput()); + onCompletionReply(result); }); + + process->start(); + process->write(jsonStr.toUtf8()); + process->closeWriteChannel(); } void OllieGhostProvider::onCompletionReply(const QString &result) @@ -464,4 +475,4 @@ QString OllieGhostProvider::gatherSuffix() const KTextEditor::Cursor endCursor(doc->lines() - 1, doc->lineLength(doc->lines() - 1)); KTextEditor::Range suffixRange(cursor, endCursor); return doc->text(suffixRange); -} +} \ No newline at end of file diff --git a/kate/ollie_ghost.h b/kate/ollie_ghost.h index 767a43a..028d0a1 100644 --- a/kate/ollie_ghost.h +++ b/kate/ollie_ghost.h @@ -7,7 +7,6 @@ #include #include -#include #include #include #include @@ -28,7 +27,7 @@ class GhostOverlay; * * Flow: * 1. Cursor moves or text changes → debounce timer starts (500ms) - * 2. Timer fires → gather prefix/suffix, call D-Bus Complete asynchronously + * 2. Timer fires → gather prefix/suffix, call 9P Complete asynchronously * 3. Result arrives → store suggestion lines, emit inlineNotesChanged * 4. paintInlineNote renders first line; GhostOverlay renders the rest * 5. Tab → accept (insert text), any other input → dismiss @@ -38,7 +37,7 @@ class OllieGhostProvider : public KTextEditor::InlineNoteProvider Q_OBJECT public: - explicit OllieGhostProvider(KTextEditor::View *view, QDBusInterface *iface, class OllieKatePlugin *plugin, QObject *parent = nullptr); + explicit OllieGhostProvider(KTextEditor::View *view, class OllieKatePlugin *plugin, QObject *parent = nullptr); ~OllieGhostProvider() override; // InlineNoteProvider interface @@ -90,7 +89,6 @@ private: QString gatherSuffix() const; KTextEditor::View *m_view; - QDBusInterface *m_iface; OllieKatePlugin *m_plugin; QTimer *m_debounce; GhostOverlay *m_overlay = nullptr; @@ -106,7 +104,7 @@ private: int m_historyIndex = -1; // current index into m_history bool m_enabled = true; // ghost completions active - bool m_requesting = false; // true while D-Bus call is in flight + bool m_requesting = false; // true while 9P call is in flight }; /** diff --git a/kate/ollie_kate.cpp b/kate/ollie_kate.cpp index 2bd9360..3ffc499 100644 --- a/kate/ollie_kate.cpp +++ b/kate/ollie_kate.cpp @@ -476,7 +476,7 @@ OllieKateView::~OllieKateView() delete m_toolView; } -// --- D-Bus signal handlers --- +// --- Signal handlers --- void OllieKateView::onChatUpdated(const QString &session_id, qlonglong offset, const QString &new_text) { @@ -529,7 +529,7 @@ void OllieKateView::onSessionKilled(const QString &session_id) m_chatView->clear(); m_sessionLabel->setText("No session"); m_cwdLabel->setText(""); - // Defer session switch to let Qt finish processing the D-Bus signal. + // Defer session switch to let Qt finish processing the signal. // Calling render() synchronously here can crash because the QTextDocument // is still tearing down resources from the clear() above. QTimer::singleShot(0, this, &OllieKateView::refreshSessions); @@ -992,8 +992,8 @@ void OllieKateView::setupGhostProvider() m_ghost = nullptr; } - // Ghost provider disabled until 9P completion is implemented - // TODO: create ghost provider with 9P-based completion + // Create ghost provider with 9P-based completion + m_ghost = new OllieGhostProvider(view, m_plugin, this); // Install event filter on the view widget for Tab interception if (QWidget *proxy = view->focusProxy()) { diff --git a/test-e2e.sh b/test-e2e.sh deleted file mode 100755 index 3d4e339..0000000 --- a/test-e2e.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/sh -# End-to-end test for ollie-kde Phase 2 -# Run this while the daemon is running: make run -set -e - -SERVICE="org.ollie.SessionManager" -PATH_OBJ="/org/ollie/SessionManager" -IFACE="org.ollie.SessionManager" - -call() { - dbus-send --session --dest=$SERVICE --type=method_call --print-reply \ - $PATH_OBJ "$IFACE.$1" "${@:2}" -} - -echo "=== ListBackends ===" -call ListBackends - -echo "" -echo "=== ListAgents ===" -call ListAgents - -echo "" -echo "=== CreateSession ===" -RESULT=$(dbus-send --session --dest=$SERVICE --type=method_call --print-reply \ - $PATH_OBJ $IFACE.CreateSession \ - string:"$HOME" string:"" string:"" string:"default" string:"" string:"") -echo "$RESULT" -SESSION_ID=$(echo "$RESULT" | grep 'string "' | head -1 | sed 's/.*string "//;s/"//') -echo "Session ID: $SESSION_ID" - -if [ -z "$SESSION_ID" ]; then - echo "FAIL: no session created" - exit 1 -fi - -echo "" -echo "=== GetState ===" -call GetState string:"$SESSION_ID" - -echo "" -echo "=== GetConfig ===" -call GetConfig string:"$SESSION_ID" - -echo "" -echo "=== Submit prompt ===" -call Submit string:"$SESSION_ID" string:"Say hello in exactly 5 words." - -echo "" -echo "=== Waiting 5s for response... ===" -sleep 5 - -echo "" -echo "=== GetState (should be idle) ===" -call GetState string:"$SESSION_ID" - -echo "" -echo "=== GetChat (offset 0) ===" -dbus-send --session --dest=$SERVICE --type=method_call --print-reply \ - $PATH_OBJ $IFACE.GetChat \ - string:"$SESSION_ID" int64:0 - -echo "" -echo "=== GetUsage ===" -call GetUsage string:"$SESSION_ID" - -echo "" -echo "=== GetCost ===" -call GetCost string:"$SESSION_ID" - -echo "" -echo "=== GetContext (first 200 chars) ===" -CONTEXT=$(dbus-send --session --dest=$SERVICE --type=method_call --print-reply \ - $PATH_OBJ $IFACE.GetContext string:"$SESSION_ID" 2>&1) -echo "$CONTEXT" | head -5 - -echo "" -echo "=== KillSession ===" -call KillSession string:"$SESSION_ID" - -echo "" -echo "=== ListSessions (should be empty) ===" -call ListSessions - -echo "" -echo "=== DONE ===" diff --git a/test-peers.sh b/test-peers.sh deleted file mode 100755 index 81f770c..0000000 --- a/test-peers.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh -# Test peer-to-peer agent communication -# Run while the daemon is running: make run -set -e - -SERVICE="org.ollie.SessionManager" -OBJ="/org/ollie/SessionManager" -IFACE="org.ollie.SessionManager" - -echo "=== Create session A ===" -A=$(dbus-send --session --dest=$SERVICE --type=method_call --print-reply \ - $OBJ $IFACE.CreateSession string:"$HOME" string:"" string:"" string:"default" string:"" string:"" | grep 'string "' | head -1 | sed 's/.*string "//;s/"//') -echo "A: $A" - -echo "=== Create session B ===" -B=$(dbus-send --session --dest=$SERVICE --type=method_call --print-reply \ - $OBJ $IFACE.CreateSession string:"$HOME" string:"" string:"" string:"default" string:"" string:"" | grep 'string "' | head -1 | sed 's/.*string "//;s/"//') -echo "B: $B" - -echo "" -echo "=== PeerAdd: A registers B ===" -dbus-send --session --dest=$SERVICE --type=method_call --print-reply \ - $OBJ $IFACE.PeerAdd string:"$A" string:"$B" - -echo "" -echo "=== PeerList ===" -dbus-send --session --dest=$SERVICE --type=method_call --print-reply \ - $OBJ $IFACE.PeerList string:"$A" - -echo "" -echo "=== PeerSubmit: A sends to B ===" -dbus-send --session --dest=$SERVICE --type=method_call --print-reply \ - $OBJ $IFACE.PeerSubmit string:"$A" string:"$B" \ - string:"Reply with exactly: PEER_OK" - -echo "" -echo "=== Waiting 8s for B to respond... ===" -sleep 8 - -echo "" -echo "=== B's chat ===" -dbus-send --session --dest=$SERVICE --type=method_call --print-reply \ - $OBJ $IFACE.GetChat string:"$B" int64:0 - -echo "" -echo "=== PeerRemove ===" -dbus-send --session --dest=$SERVICE --type=method_call --print-reply \ - $OBJ $IFACE.PeerRemove string:"$A" string:"$B" - -echo "" -echo "=== Cleanup ===" -dbus-send --session --dest=$SERVICE --type=method_call --print-reply \ - $OBJ $IFACE.KillSession string:"$A" > /dev/null -dbus-send --session --dest=$SERVICE --type=method_call --print-reply \ - $OBJ $IFACE.KillSession string:"$B" > /dev/null -echo "=== DONE ==="