copilotoffice 2.1.0 → 2.3.0
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 +225 -192
- package/bin/copilotoffice.js +39 -39
- package/dist/electron/main.js +599 -126
- package/dist/electron/terminal/events-watcher.js +53 -2
- package/dist/electron/terminal/ipc-relay.js +49 -1
- package/dist/electron/terminal/preload.js +57 -13
- package/dist/electron/terminal/server.js +6125 -940
- package/dist/game.bundle.js +611 -206
- package/package.json +62 -58
- package/src/index.html +44 -44
package/README.md
CHANGED
|
@@ -1,192 +1,225 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
A 2D pixel-art RPG-style game where you walk around a virtual office and interact with AI agents. Each NPC runs a real Copilot CLI session with full coding capabilities — plan tasks, debug code, and orchestrate multi-agent workflows from inside a game.
|
|
4
|
-
|
|
5
|
-

|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Pixel-art office environment** — every sprite is procedurally generated in code; there are no external image assets
|
|
10
|
+
- **Real Copilot agents** — each NPC runs an actual Copilot CLI session, rendered live in an xterm.js terminal
|
|
11
|
+
- **3 active NPC agents by default**, each with a distinct personality:
|
|
12
|
+
- **Gene** (Generalist) — general-purpose coding, debugging, and research
|
|
13
|
+
- **Dan** (Debugger) — bug investigation and root-cause analysis
|
|
14
|
+
- **Alice** (Admin) — has direct access to edit this game's own source code (`workingDir: '.'`)
|
|
15
|
+
- **6 reserve agents** — Azure (Cloud Wizard), Val (Validator), Rex (Deployer), Doc (Code Doctor), Scout (Ranger), and Penny (Accountant) have pre-generated sprites ready to seat at an empty desk
|
|
16
|
+
- **Arthur (the Architect)** — hosts Meeting Mode and appears in fleet v-team offices (can be toggled into the default office in config)
|
|
17
|
+
- **Teams remote agents** — bring any agent online in a Microsoft Teams channel thread; anyone can reply in-thread to drive the agent's terminal session and get answers posted back (feature-flagged)
|
|
18
|
+
- **Multi-office management** — switch between projects with independent agent state and working directories per office
|
|
19
|
+
- **Meeting Mode** — a private meeting room where Arthur decomposes a complex request into a structured, reviewable plan
|
|
20
|
+
- **Fleet execution** — approved plans spin up parallel agent sessions in a dedicated v-team office
|
|
21
|
+
- **Real-time status badges** — agent states (slacking → starting → ready ↔ waiting/thinking) with animated indicators
|
|
22
|
+
- **Toast & OS notifications** — configurable per-event notifications for agent activity
|
|
23
|
+
- **Session persistence** — offices, seated agents, and terminal sessions survive restarts
|
|
24
|
+
- **Player & sprite customization** — customize your character's appearance and colors
|
|
25
|
+
- **Mini-games** — a built-in Galaxian arcade game (Pong and Basketball are also included behind feature flags)
|
|
26
|
+
- **Hot reload** development mode with file watching
|
|
27
|
+
|
|
28
|
+
## Tech Stack
|
|
29
|
+
|
|
30
|
+
- **Phaser 3** — 2D game framework (the sole renderer)
|
|
31
|
+
- **Electron 40+** — desktop shell with a Node.js main process
|
|
32
|
+
- **TypeScript** — strict mode throughout
|
|
33
|
+
- **esbuild** — fast bundling for both the game and Electron code
|
|
34
|
+
- **xterm.js** — terminal emulator for agent conversations
|
|
35
|
+
- **node-pty** — pseudo-terminal that hosts the Copilot CLI
|
|
36
|
+
- **@github/copilot-sdk** — SDK control plane for the `ui-server` terminal backend
|
|
37
|
+
- **ws** — WebSocket transport (SDK runtime + Teams real-time receive)
|
|
38
|
+
|
|
39
|
+
### Terminal backends
|
|
40
|
+
|
|
41
|
+
The terminal server (`electron/terminal/server.ts`) selects a backend via the `COPILOT_TERMINAL_BACKEND` environment variable:
|
|
42
|
+
|
|
43
|
+
- **`node-pty`** (fallback, always available) — spawns the real Copilot TUI directly, one PTY per agent
|
|
44
|
+
- **`ui-server`** (default) — node-pty hosts one `copilot --ui-server` runtime per office and the Copilot SDK attaches over a local port; automatically falls back to `node-pty` when the CLI can't host `--ui-server`
|
|
45
|
+
- **`sdk`** (legacy) — the SDK spawns its own headless runtime over stdio
|
|
46
|
+
|
|
47
|
+
## Getting Started
|
|
48
|
+
|
|
49
|
+
### Prerequisites
|
|
50
|
+
|
|
51
|
+
To use the app **in full** you'll need:
|
|
52
|
+
|
|
53
|
+
- **Node.js 18+** and **npm**
|
|
54
|
+
- **GitHub Copilot access** — the agents run the real Copilot CLI, so you must be signed in to a GitHub account with an active Copilot subscription. The CLI runtime ships with the app via the `@github/copilot-sdk` platform package; on first run, authenticate through the CLI as prompted.
|
|
55
|
+
- **(Teams remote agents only) Azure CLI** — the Teams feature acquires Microsoft Graph and IC3 tokens via `az account get-access-token`, so you must have the [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) installed and be logged in (`az login`) with an account that has access to the target Teams channel. This feature is off by default and enabled in Settings.
|
|
56
|
+
|
|
57
|
+
### Install from npm (global command)
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npm i -g copilotoffice
|
|
61
|
+
copilotoffice
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Install from source (development)
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
git clone https://github.com/dan1510123/CopilotOffice.git
|
|
68
|
+
cd CopilotOffice
|
|
69
|
+
npm install
|
|
70
|
+
|
|
71
|
+
# Build and run
|
|
72
|
+
npm start
|
|
73
|
+
|
|
74
|
+
# Development mode (with hot reload)
|
|
75
|
+
npm run dev
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Controls
|
|
79
|
+
|
|
80
|
+
| Key | Action |
|
|
81
|
+
|-----|--------|
|
|
82
|
+
| `WASD` / `Arrow Keys` | Move around the office |
|
|
83
|
+
| `Shift` | Sprint (2x speed) |
|
|
84
|
+
| `E` | Interact with nearby agent or object |
|
|
85
|
+
| `F10` | Close terminal |
|
|
86
|
+
| `Escape` | Close terminal or mini-game |
|
|
87
|
+
| `Ctrl+Shift+N` | New terminal session (terminal focused) |
|
|
88
|
+
|
|
89
|
+
## Project Structure
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
CopilotOffice/
|
|
93
|
+
├── electron/ # Electron main process
|
|
94
|
+
│ ├── main.ts # Window, IPC handlers, hot reload
|
|
95
|
+
│ ├── nonTerminalIpc.ts # Non-terminal IPC handlers
|
|
96
|
+
│ ├── officeFileStore.ts # Office persistence on disk
|
|
97
|
+
│ ├── cli-bridge.ts # Legacy placeholder (not used at runtime)
|
|
98
|
+
│ ├── terminal/ # Terminal server subsystem
|
|
99
|
+
│ │ ├── server.ts # PTY/SDK owner (forked child process)
|
|
100
|
+
│ │ ├── terminal-backend.ts # Backend selection (node-pty / ui-server / sdk)
|
|
101
|
+
│ │ ├── pty-registry.ts # Live PTY/session bookkeeping
|
|
102
|
+
│ │ ├── agent-viewers.ts # Active-viewer dual-key invariant helpers
|
|
103
|
+
│ │ ├── office-foreground.ts # Foreground session selection (ui-server)
|
|
104
|
+
│ │ ├── session-repair.ts # Session recovery
|
|
105
|
+
│ │ ├── ipc-relay.ts # IPC bridge (renderer ↔ main ↔ server)
|
|
106
|
+
│ │ ├── preload.ts # Context bridge (window.copilotBridge)
|
|
107
|
+
│ │ ├── protocol.ts # IPC message type definitions
|
|
108
|
+
│ │ ├── event-source.ts # Backend-agnostic event source
|
|
109
|
+
│ │ └── events-watcher.ts # Copilot CLI event file parser
|
|
110
|
+
│ └── teams/ # Teams remote agents (main-process service)
|
|
111
|
+
│ ├── teamsService.ts # Orchestrator (register/route/reply lifecycle)
|
|
112
|
+
│ ├── auth.ts # Graph + IC3 tokens via `az`
|
|
113
|
+
│ ├── graphClient.ts # Send channel messages
|
|
114
|
+
│ ├── trouterClient.ts # Real-time receive (WebSocket)
|
|
115
|
+
│ ├── chatsvcClient.ts # Poll fallback receive
|
|
116
|
+
│ ├── messageFilter.ts # Dedup / marker / classify pipeline
|
|
117
|
+
│ ├── dispatchQueue.ts # Per-agent FIFO dispatch
|
|
118
|
+
│ ├── sessionGateway.ts # Adapter over the terminal server
|
|
119
|
+
│ ├── onlineAgentsStore.ts # Online-agent persistence + GC
|
|
120
|
+
│ └── ... # channelLink, marker, chunk, resolvers, IPC
|
|
121
|
+
├── src/ # Renderer process (Phaser + DOM)
|
|
122
|
+
│ ├── main.ts # Entry point — DOM layout, Phaser init, IPC wiring
|
|
123
|
+
│ ├── index.html # HTML host page
|
|
124
|
+
│ ├── scenes/ # Phaser scenes
|
|
125
|
+
│ │ ├── BootScene.ts # Procedural sprite generation
|
|
126
|
+
│ │ ├── OfficeScene.ts # Main game scene (layout, NPCs, interactions)
|
|
127
|
+
│ │ └── MeetingScene.ts # Meeting room with Arthur for planning
|
|
128
|
+
│ ├── entities/ # Game entities (Player, NPC)
|
|
129
|
+
│ ├── sprites/ # Procedural sprite generation + animation
|
|
130
|
+
│ ├── ui/ # DOM overlays
|
|
131
|
+
│ │ ├── TerminalOverlay.ts # xterm.js terminal for agent sessions
|
|
132
|
+
│ │ ├── SeriousTerminalController.ts # Split-pane terminal controller
|
|
133
|
+
│ │ ├── FleetDashboard.ts # Fleet execution dashboard
|
|
134
|
+
│ │ ├── SettingsPanel.ts # Settings overlay
|
|
135
|
+
│ │ ├── TeamsSettingsOverlay.ts # Teams feature settings
|
|
136
|
+
│ │ ├── SpriteCustomizerPanel.ts # Player appearance customization
|
|
137
|
+
│ │ ├── GalaxianGame.ts # Galaxian mini-game
|
|
138
|
+
│ │ ├── PongGame.ts / BasketballGame.ts # Mini-games (feature-flagged)
|
|
139
|
+
│ │ ├── NotificationService.ts / NotificationSettingsPanel.ts / ToastNotification.ts
|
|
140
|
+
│ │ └── CameraDragController.ts / DialogBox.ts
|
|
141
|
+
│ ├── input/ # Keyboard focus management (InputManager + listeners)
|
|
142
|
+
│ ├── office/ # Multi-office state management (officeManager.ts)
|
|
143
|
+
│ ├── meeting/ # Meeting mode & fleet orchestration
|
|
144
|
+
│ │ ├── types.ts / planParser.ts / planApproval.ts
|
|
145
|
+
│ │ └── fleetOrchestrator.ts / fleetTracker.ts / fleetVisualizer.ts
|
|
146
|
+
│ ├── layouts/ # Layout system
|
|
147
|
+
│ │ ├── types.ts / index.ts # Layout registry + behaviors
|
|
148
|
+
│ │ ├── default/ # Default office layout
|
|
149
|
+
│ │ └── fleet/ # Fleet v-team layout
|
|
150
|
+
│ └── config/ # Static configuration
|
|
151
|
+
│ ├── agents.ts # Agent definitions, reserve + fleet config
|
|
152
|
+
│ ├── depths.ts / zIndex.ts # Phaser depth + DOM z-index constants
|
|
153
|
+
│ ├── notifications.ts # Notification event settings
|
|
154
|
+
│ ├── meetingPrompt.ts # Meeting coordinator prompt
|
|
155
|
+
│ └── playerCustomization.ts # Player color customization
|
|
156
|
+
└── dist/ # Build output
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Adding New Agents
|
|
160
|
+
|
|
161
|
+
Edit `src/config/agents.ts` to add new NPCs. Six reserve agent slots (Azure, Val, Rex, Doc, Scout, Penny) already have pre-generated sprites — activate one by adding its config, or add a brand-new entry to the `AGENTS` array:
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
{
|
|
165
|
+
id: 'unique-id',
|
|
166
|
+
name: 'Display Name',
|
|
167
|
+
skill: 'general',
|
|
168
|
+
sprite: 'sprite_key',
|
|
169
|
+
color: 0xff0000, // Hex color for the procedural sprite
|
|
170
|
+
position: { x: 5, y: 7 }, // Grid position in the office (20×12 tile grid)
|
|
171
|
+
greeting: "Hello message shown when the player approaches",
|
|
172
|
+
description: 'Short description',
|
|
173
|
+
workingDir: 'optional/path', // Optional custom working directory
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Sprites are auto-generated from the color — no image assets needed.
|
|
178
|
+
|
|
179
|
+
> **Tip:** Don't hardcode agent IDs in scene/layout/dashboard logic. Use the named
|
|
180
|
+
> constants exported from `src/config/agents.ts` (`GENERALIST_AGENT_ID`,
|
|
181
|
+
> `DEBUGGER_AGENT_ID`, `ADMIN_AGENT_ID`, `ARCHITECT_AGENT_ID`, `DEFAULT_PLAN_AGENT_IDS`).
|
|
182
|
+
|
|
183
|
+
## Development
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# Watch mode with hot reload
|
|
187
|
+
npm run dev
|
|
188
|
+
|
|
189
|
+
# Build only (no run)
|
|
190
|
+
npm run build
|
|
191
|
+
|
|
192
|
+
# Run without rebuilding
|
|
193
|
+
npm run electron
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Testing
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
npm run test # Vitest unit/integration suite
|
|
200
|
+
npm run test:coverage # Vitest with coverage output
|
|
201
|
+
npm run test:e2e # Playwright end-to-end tests (runs a build first)
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Release channels
|
|
205
|
+
|
|
206
|
+
- **Stable**: `npm i -g copilotoffice` (uses the npm `latest` dist-tag)
|
|
207
|
+
- **Beta**: `npm i -g copilotoffice@beta` (uses the npm `beta` dist-tag)
|
|
208
|
+
|
|
209
|
+
For maintainers: pushing to GitHub is not enough for `npm i -g copilotoffice` by name —
|
|
210
|
+
you must publish to npm. Typical flow:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
npm run build
|
|
214
|
+
npm test
|
|
215
|
+
npm version patch
|
|
216
|
+
npm publish
|
|
217
|
+
|
|
218
|
+
# Beta example
|
|
219
|
+
npm version prerelease --preid=beta
|
|
220
|
+
npm publish --tag beta
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## License
|
|
224
|
+
|
|
225
|
+
ISC
|
package/bin/copilotoffice.js
CHANGED
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const { spawn } = require('child_process');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
|
|
6
|
-
function run() {
|
|
7
|
-
let electronBinary;
|
|
8
|
-
try {
|
|
9
|
-
electronBinary = require('electron');
|
|
10
|
-
} catch (error) {
|
|
11
|
-
console.error('[copilotoffice] Electron is not available. Try reinstalling the package.');
|
|
12
|
-
console.error(error);
|
|
13
|
-
process.exit(1);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const appRoot = path.resolve(__dirname, '..');
|
|
17
|
-
const child = spawn(electronBinary, [appRoot], {
|
|
18
|
-
stdio: 'inherit',
|
|
19
|
-
windowsHide: false,
|
|
20
|
-
env: {
|
|
21
|
-
...process.env,
|
|
22
|
-
COPILOT_OFFICE_ENABLE_WATCHER: '0',
|
|
23
|
-
COPILOT_OFFICE_OPEN_DEVTOOLS: '0',
|
|
24
|
-
COPILOT_OFFICE_CLI_MODE: '1',
|
|
25
|
-
},
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
child.on('exit', (code) => {
|
|
29
|
-
process.exit(code ?? 0);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
child.on('error', (error) => {
|
|
33
|
-
console.error('[copilotoffice] Failed to launch Electron.');
|
|
34
|
-
console.error(error);
|
|
35
|
-
process.exit(1);
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
run();
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn } = require('child_process');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
function run() {
|
|
7
|
+
let electronBinary;
|
|
8
|
+
try {
|
|
9
|
+
electronBinary = require('electron');
|
|
10
|
+
} catch (error) {
|
|
11
|
+
console.error('[copilotoffice] Electron is not available. Try reinstalling the package.');
|
|
12
|
+
console.error(error);
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const appRoot = path.resolve(__dirname, '..');
|
|
17
|
+
const child = spawn(electronBinary, [appRoot], {
|
|
18
|
+
stdio: 'inherit',
|
|
19
|
+
windowsHide: false,
|
|
20
|
+
env: {
|
|
21
|
+
...process.env,
|
|
22
|
+
COPILOT_OFFICE_ENABLE_WATCHER: '0',
|
|
23
|
+
COPILOT_OFFICE_OPEN_DEVTOOLS: '0',
|
|
24
|
+
COPILOT_OFFICE_CLI_MODE: '1',
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
child.on('exit', (code) => {
|
|
29
|
+
process.exit(code ?? 0);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
child.on('error', (error) => {
|
|
33
|
+
console.error('[copilotoffice] Failed to launch Electron.');
|
|
34
|
+
console.error(error);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
run();
|