Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Build-time, non-secret. Cloud origin used by the "Dewee Cloud" profile.
WXT_DEWEE_CLOUD_ORIGIN=https://app.dewee.sh

# Live Playwright scenarios only (never baked into the build). Use a personal,
# owner-bound API key with operator.read + operator.write — never the master token.
E2E_GATEWAY_URL=http://localhost:18790
E2E_GATEWAY_API_KEY=
E2E_WORKSPACE_ID=
# Live revocation scenario only, local test gateway: the key owner and the gateway admin token.
E2E_OWNER_ID=
E2E_GATEWAY_ADMIN_TOKEN=
61 changes: 61 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: CI

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
check:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm typecheck
- run: pnpm test
- run: pnpm build
- run: pnpm zip
- uses: actions/upload-artifact@v4
with:
name: dewee-chrome-ext
path: .output/*.zip
# .output is a dot directory, which upload-artifact skips unless told otherwise.
include-hidden-files: true
if-no-files-found: error

e2e:
runs-on: ubuntu-latest
needs: check
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm exec playwright install --with-deps chromium
- run: pnpm test:e2e
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: |
playwright-report/
test-results/
if-no-files-found: ignore
56 changes: 56 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Release

on:
push:
tags: ['v*']

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
# Dependency install scripts run in this job, so it gets no write token and keeps none in .git.
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm lint && pnpm typecheck && pnpm test
- name: Check tag matches package version
run: test "v$(node -p "require('./package.json').version")" = "${GITHUB_REF_NAME}"
# Unpacked-install zip (pinned extension ID) and Chrome Web Store zip (no manifest key).
- run: pnpm zip && pnpm zip:store
- name: Collect release files
run: |
mkdir release
cp .output/*.zip release/
for f in .output-store/*.zip; do cp "$f" "release/$(basename "${f%.zip}")-store.zip"; done
cp CHANGELOG.md release/
- uses: actions/upload-artifact@v4
with:
name: release
path: release/
retention-days: 7

publish:
needs: build
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
steps:
- uses: actions/download-artifact@v4
with:
name: release
path: release
- name: Publish GitHub release
env:
GH_TOKEN: ${{ github.token }}
run: gh release create "$GITHUB_REF_NAME" release/*.zip --repo "$GITHUB_REPOSITORY" --title "$GITHUB_REF_NAME" --notes-file release/CHANGELOG.md
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
node_modules/
.output/
.output-e2e/
.output-store/
.wxt/
dist/
coverage/
test-results/
playwright-report/
*.log
.env
.env.*
!.env.example
65 changes: 65 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# AGENTS.md

Guidance for humans and coding agents contributing to `nextlevelbuilder/dewee-chrome-ext`.

## What this repo is

A thin Chrome Manifest V3 client for Dewee. It renders a right side panel for chat with Dewee agents (Super Agent pinned first) and renders server-defined credential request cards. The Dewee Gateway is authoritative for agents, tenants, sessions, permissions and the credential store. Backend changes belong in [`nextlevelbuilder/dewee`](https://github.com/nextlevelbuilder/dewee); never copy Dewee source into this repo.

Read before changing code: [docs/architecture.md](docs/architecture.md), [docs/api-contract.md](docs/api-contract.md), [docs/auth-threat-model.md](docs/auth-threat-model.md), [docs/credential-threat-model.md](docs/credential-threat-model.md), [docs/development.md](docs/development.md).

## Commands

```bash
pnpm install # also runs `wxt prepare`
pnpm dev # Chrome with the extension loaded and hot reload
pnpm lint
pnpm typecheck
pnpm test # unit + integration (Vitest)
pnpm test:e2e # builds, then runs Playwright against the unpacked build
pnpm build # .output/chrome-mv3
pnpm zip # sideload zip (keeps the pinned extension key)
pnpm zip:store # Chrome Web Store zip (manifest without `key`)
```

Run `pnpm lint && pnpm typecheck && pnpm test && pnpm build` before every push. CI runs the same gates plus e2e.

## Issue and PR workflow (required for every contributor)

Status labels show who is working on what so contributors do not step on each other.

| Label | When to set it |
|---|---|
| `in progress` | You started work. Assign yourself at the same time. |
| `blocked` | Work cannot continue (missing backend API, decision, credential). Comment with the blocker and a link. |
| `in review` | Implementation is done and an isolated reviewer (human or a subagent with fresh context) is reviewing. |
| `done` | The PR is open and linked with `Closes #N` / `Refs #N`. |
| `shipped` | The PR is merged into `main`. |

Rules:

1. Before starting, check the issue is not already `in progress` with another assignee. If it is, coordinate on the issue instead of starting parallel work.
2. Move one label at a time (remove the previous status label when you add the next).
3. Code review runs in an isolated context (a separate reviewer or subagent that did not write the code). Address blocking findings before `done`.
4. If you find an unrelated bug, gap or hardening need, open a new issue (labels `bug` or `security` plus `ai-handle` when an agent can take it) instead of widening the current PR.
5. Backend dependencies go to `nextlevelbuilder/dewee` as linked issues/PRs. Do not ship UI-only mocks for missing backend APIs.
6. Conventional commits, no secrets, no AI attribution in commit subjects.

## Security rules (non-negotiable)

- Never put secrets in chat messages, `chat.send`, URLs, logs, telemetry, Chrome `storage.local`/`sync`, or app-wide React state. Secret values live only in the credential form's local state and go only to the action respond endpoint.
- Never use the Dewee gateway master token as a client credential. Self-hosted mode uses a personal scoped API key (`operator.read`/`operator.write`).
- Never render agent-generated HTML. Cards render from a fixed list of kinds validated with Zod; markdown is sanitized with DOMPurify.
- No remote code, no `eval`, strict extension CSP. Host permissions are requested per gateway origin at runtime, never `<all_urls>`.
- The side panel never reads the active page.

## Code layout

- `src/entrypoints/` thin WXT entrypoints (background, sidepanel, options).
- `src/background/` service worker logic; `src/sidepanel/` and `src/options/` React UI.
- `src/api/` one typed `DeweeClient` for both modes (self-hosted Gateway and Cloud BFF) plus response schemas.
- `src/protocol/` Zod schemas for SSE events, UI actions and the background⇄panel messages.
- `src/auth/`, `src/chat/`, `src/credentials/`, `src/shared/` feature modules.
- `tests/unit`, `tests/integration`, `tests/e2e`.

Keep files small and focused; kebab-case for new non-component files, PascalCase for React components.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Changelog

## 0.1.0 — unreleased

First MVP of the Dewee Chrome extension.

- Side panel chat with Dewee agents: streaming, stop, retry, sessions, history paging, new chat, and reconcile after a lost stream without re-sending.
- Two connection modes: Dewee Cloud (OAuth Authorization Code + PKCE) and self-hosted Gateway (personal scoped API key).
- Workspace picker and searchable agent picker with Super Agent pinned first.
- Cards: secure credentials form for `secret_request`, `oauth_request`, choice, command preview, progress; other kinds shown read-only.
- Pending-card badge, English and Vietnamese, light/dark/system theme, keyboard shortcuts (Alt+Shift+D, Alt+N, /, Esc).
- Credentials kept in `storage.session` by default; opt-in "remember".
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Next Level Builder

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
49 changes: 47 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,47 @@
# dewee-chrome-ext
Dewee Chrome Extension: secure multi-workspace agent chat, Super Agent and credential requests in a Chrome side panel
# Dewee Chrome Extension

Chat with your Dewee agents, with Super Agent pinned first, in Chrome's side panel. When an agent needs an API key or an OAuth connection, the extension shows a secure card, so you never paste secrets into chat.

- **Two connection modes:** Dewee Cloud (sign in with OAuth + PKCE) or a self-hosted Dewee Gateway (personal API key with `operator.read` + `operator.write`).
- **Workspaces and agents:** pick a workspace, search agents, and keep separate sessions per agent.
- **Reliable chat:** streaming, stop, retry, history, new chat. If the connection drops, the panel checks the server instead of sending your message twice.
- **Credential cards:** secrets stay in the form and go only to Dewee's respond endpoint. Nothing secret is stored by the extension.
- **Pending badge**, English and Vietnamese, light/dark/system theme, keyboard shortcuts.

## Install (development build)

```bash
pnpm install
pnpm build
```

Open `chrome://extensions`, enable **Developer mode**, choose **Load unpacked** and select `.output/chrome-mv3`. Pin the extension and click it (or press `Alt+Shift+D`) to open the side panel.

## Connect

- **Dewee Cloud:** choose *Dewee Cloud* and *Sign in*. You approve access on Dewee, then return to the panel.
- **Self-hosted:** choose *Self-hosted*, enter your Gateway URL (HTTPS, or `http://localhost` for development) and a personal API key created in Dewee. The Gateway operator must allow the origin `chrome-extension://poicgajeapmbcilfbeobdfedibiffbbm` (`GOCLAW_ALLOWED_ORIGINS`). Never use the gateway master token.

By default the credential is kept only until Chrome closes. Tick *Remember on this device* to keep it on disk.

## Keyboard shortcuts

| Keys | Action |
|---|---|
| `Alt+Shift+D` | Open the side panel (change in `chrome://extensions/shortcuts`) |
| `Enter` / `Shift+Enter` | Send / new line |
| `Esc` | Stop the reply |
| `Alt+N` | New chat |
| `/` | Focus the message box |

## Docs

- [Architecture](docs/architecture.md)
- [Extension API contract](docs/api-contract.md)
- [Authentication threat model](docs/auth-threat-model.md)
- [Credential request threat model](docs/credential-threat-model.md)
- [Development](docs/development.md) and [contributor workflow](AGENTS.md)

## License

[MIT](LICENSE)
Empty file added docs/09-security.md
Empty file.
Loading
Loading