@esotech/contextuate 2.0.0 → 2.1.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 +169 -1
- package/dist/commands/claude.d.ts +21 -0
- package/dist/commands/claude.js +213 -0
- package/dist/commands/context.d.ts +1 -0
- package/dist/commands/create.d.ts +3 -0
- package/dist/commands/index.d.ts +4 -0
- package/dist/commands/init.d.ts +7 -0
- package/dist/commands/init.js +67 -6
- package/dist/commands/install.d.ts +28 -0
- package/dist/commands/install.js +116 -11
- package/dist/commands/monitor.d.ts +55 -0
- package/dist/commands/monitor.js +1007 -0
- package/dist/commands/remove.d.ts +3 -0
- package/dist/commands/run.d.ts +6 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +113 -1
- package/dist/monitor/daemon/circuit-breaker.d.ts +121 -0
- package/dist/monitor/daemon/circuit-breaker.js +552 -0
- package/dist/monitor/daemon/cli.d.ts +8 -0
- package/dist/monitor/daemon/cli.js +82 -0
- package/dist/monitor/daemon/index.d.ts +137 -0
- package/dist/monitor/daemon/index.js +695 -0
- package/dist/monitor/daemon/notifier.d.ts +25 -0
- package/dist/monitor/daemon/notifier.js +98 -0
- package/dist/monitor/daemon/processor.d.ts +89 -0
- package/dist/monitor/daemon/processor.js +455 -0
- package/dist/monitor/daemon/state.d.ts +80 -0
- package/dist/monitor/daemon/state.js +162 -0
- package/dist/monitor/daemon/watcher.d.ts +47 -0
- package/dist/monitor/daemon/watcher.js +171 -0
- package/dist/monitor/daemon/wrapper-manager.d.ts +106 -0
- package/dist/monitor/daemon/wrapper-manager.js +374 -0
- package/dist/monitor/hooks/emit-event.js +652 -0
- package/dist/monitor/persistence/file-store.d.ts +88 -0
- package/dist/monitor/persistence/file-store.js +335 -0
- package/dist/monitor/persistence/index.d.ts +7 -0
- package/dist/monitor/persistence/index.js +10 -0
- package/dist/monitor/server/adapters/redis.d.ts +38 -0
- package/dist/monitor/server/adapters/redis.js +213 -0
- package/dist/monitor/server/adapters/unix-socket.d.ts +33 -0
- package/dist/monitor/server/adapters/unix-socket.js +182 -0
- package/dist/monitor/server/broker.d.ts +135 -0
- package/dist/monitor/server/broker.js +475 -0
- package/dist/monitor/server/cli.d.ts +8 -0
- package/dist/monitor/server/cli.js +98 -0
- package/dist/monitor/server/fastify.d.ts +16 -0
- package/dist/monitor/server/fastify.js +184 -0
- package/dist/monitor/server/index.d.ts +36 -0
- package/dist/monitor/server/index.js +153 -0
- package/dist/monitor/server/websocket.d.ts +80 -0
- package/dist/monitor/server/websocket.js +453 -0
- package/dist/monitor/ui/assets/index-4IssW9On.js +59 -0
- package/dist/monitor/ui/assets/index-vo9hLe5R.css +32 -0
- package/dist/monitor/ui/favicon.png +0 -0
- package/dist/monitor/ui/index.html +14 -0
- package/dist/monitor/ui/logo.png +0 -0
- package/dist/monitor/ui/logo.svg +1 -0
- package/dist/runtime/driver.d.ts +16 -0
- package/dist/runtime/tools.d.ts +10 -0
- package/dist/templates/README.md +33 -7
- package/dist/templates/agents/aegis.md +4 -0
- package/dist/templates/agents/archon.md +13 -22
- package/dist/templates/agents/atlas.md +4 -0
- package/dist/templates/agents/canvas.md +4 -0
- package/dist/templates/agents/chronicle.md +4 -0
- package/dist/templates/agents/chronos.md +4 -0
- package/dist/templates/agents/cipher.md +4 -0
- package/dist/templates/agents/crucible.md +4 -0
- package/dist/templates/agents/echo.md +4 -0
- package/dist/templates/agents/forge.md +4 -0
- package/dist/templates/agents/ledger.md +4 -0
- package/dist/templates/agents/meridian.md +4 -0
- package/dist/templates/agents/nexus.md +4 -0
- package/dist/templates/agents/pythia.md +217 -0
- package/dist/templates/agents/scribe.md +4 -0
- package/dist/templates/agents/sentinel.md +4 -0
- package/dist/templates/agents/{oracle.md → thoth.md} +11 -7
- package/dist/templates/agents/unity.md +4 -0
- package/dist/templates/agents/vox.md +4 -0
- package/dist/templates/agents/weaver.md +4 -0
- package/dist/templates/framework-agents/documentation-expert.md +3 -3
- package/dist/templates/framework-agents/tools-expert.md +8 -8
- package/dist/templates/skills/consult.md +138 -0
- package/dist/templates/skills/orchestrate.md +173 -0
- package/dist/templates/skills/pythia.md +37 -0
- package/dist/templates/standards/agent-roles.md +68 -21
- package/dist/templates/standards/coding-standards.md +9 -26
- package/dist/templates/templates/context.md +17 -2
- package/dist/templates/templates/contextuate.md +21 -28
- package/dist/templates/templates/standards/go.md +167 -0
- package/dist/templates/templates/standards/java.md +167 -0
- package/dist/templates/templates/standards/javascript.md +292 -0
- package/dist/templates/templates/standards/php.md +181 -0
- package/dist/templates/templates/standards/python.md +175 -0
- package/dist/templates/tools/agent-creator.md +252 -0
- package/dist/templates/tools/agent-creator.tool.md +2 -2
- package/dist/templates/tools/quickref.md +216 -0
- package/dist/templates/tools/spawn.md +31 -0
- package/dist/templates/tools/standards-detector.md +301 -0
- package/dist/templates/version.json +1 -1
- package/dist/types/monitor.d.ts +660 -0
- package/dist/types/monitor.js +75 -0
- package/dist/utils/git.d.ts +9 -0
- package/dist/utils/tokens.d.ts +10 -0
- package/package.json +18 -5
package/README.md
CHANGED
|
@@ -68,6 +68,7 @@ Contextuate is a directory structure and set of conventions that helps AI agents
|
|
|
68
68
|
- **`docs/ai/standards/`**: Explicit coding standards and behavioral guidelines.
|
|
69
69
|
- **`docs/ai/quickrefs/`**: Condensed documentation optimized for AI token limits.
|
|
70
70
|
- **`docs/ai/tasks/`**: A workflow for managing multi-session AI tasks.
|
|
71
|
+
- **`docs/ai/skills/`**: Slash commands that activate special behaviors (e.g., `/orchestrate`).
|
|
71
72
|
|
|
72
73
|
## How LLMs Use Contextuate
|
|
73
74
|
|
|
@@ -119,6 +120,7 @@ contextuate -V # Short form for version
|
|
|
119
120
|
| `index` | Generate a project file tree |
|
|
120
121
|
| `add-context` | Interactively add files to context |
|
|
121
122
|
| `remove` | Clean up framework files |
|
|
123
|
+
| `monitor` | Real-time Claude Code session monitoring |
|
|
122
124
|
|
|
123
125
|
---
|
|
124
126
|
|
|
@@ -168,6 +170,7 @@ contextuate install --all
|
|
|
168
170
|
contextuate install --agents archon base canvas
|
|
169
171
|
contextuate install --standards php javascript
|
|
170
172
|
contextuate install --tools quickref
|
|
173
|
+
contextuate install --skills orchestrate
|
|
171
174
|
|
|
172
175
|
# Subcommand style
|
|
173
176
|
contextuate install agents archon base
|
|
@@ -175,6 +178,7 @@ contextuate install agents --all
|
|
|
175
178
|
contextuate install standards php javascript python
|
|
176
179
|
contextuate install standards --all
|
|
177
180
|
contextuate install tools --all
|
|
181
|
+
contextuate install skills --all
|
|
178
182
|
|
|
179
183
|
# Force overwrite
|
|
180
184
|
contextuate install agents --all --force
|
|
@@ -184,14 +188,16 @@ contextuate install agents --all --force
|
|
|
184
188
|
- `-a, --agents <names...>` - Install specific agents
|
|
185
189
|
- `-s, --standards <names...>` - Install language standards
|
|
186
190
|
- `-t, --tools <names...>` - Install tools
|
|
191
|
+
- `-k, --skills <names...>` - Install skills (slash commands)
|
|
187
192
|
- `--all` - Install all available templates
|
|
188
193
|
- `-l, --list` - List available templates
|
|
189
194
|
- `-f, --force` - Overwrite existing files
|
|
190
195
|
|
|
191
196
|
**Subcommands:**
|
|
192
|
-
- `install agents [names...]` - Install agent templates
|
|
197
|
+
- `install agents [names...]` - Install agent templates (also installs skills by default)
|
|
193
198
|
- `install standards [names...]` - Install language standard templates
|
|
194
199
|
- `install tools [names...]` - Install tool templates
|
|
200
|
+
- `install skills [names...]` - Install skill templates (slash commands like `/orchestrate`)
|
|
195
201
|
|
|
196
202
|
---
|
|
197
203
|
|
|
@@ -269,6 +275,168 @@ Remove unmodified platform jump files.
|
|
|
269
275
|
contextuate remove
|
|
270
276
|
```
|
|
271
277
|
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
### `contextuate monitor`
|
|
281
|
+
|
|
282
|
+
Real-time monitoring dashboard for Claude Code sessions. Tracks tool usage, events, and session activity.
|
|
283
|
+
|
|
284
|
+
#### Architecture
|
|
285
|
+
|
|
286
|
+
The monitor uses a 3-layer architecture:
|
|
287
|
+
|
|
288
|
+
1. **Hooks** - Claude Code hooks emit events to the daemon
|
|
289
|
+
2. **Daemon** - Background process that collects and processes events (runs independently)
|
|
290
|
+
3. **UI Server** - Web dashboard and WebSocket server for real-time updates
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
294
|
+
│ Claude Code │────▶│ Daemon │────▶│ UI Server │
|
|
295
|
+
│ (Hooks) │ │ (Background) │ │ (Dashboard) │
|
|
296
|
+
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**Important:** The daemon runs independently of the UI server. Starting the monitor will spawn the daemon, but stopping the monitor will NOT stop the daemon (so it can continue collecting events). Use `--all` to stop both.
|
|
300
|
+
|
|
301
|
+
#### Commands
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
# Initial setup (interactive)
|
|
305
|
+
contextuate monitor init
|
|
306
|
+
contextuate monitor init --global # Install hooks at user level (~/.claude/)
|
|
307
|
+
contextuate monitor init --project # Install hooks at project level (.claude/)
|
|
308
|
+
|
|
309
|
+
# Start the monitor (auto-starts daemon if not running)
|
|
310
|
+
contextuate monitor
|
|
311
|
+
contextuate monitor start
|
|
312
|
+
contextuate monitor start --port 8080 # Custom HTTP port
|
|
313
|
+
contextuate monitor start --ws-port 8081 # Custom WebSocket port
|
|
314
|
+
contextuate monitor start --no-open # Don't open browser
|
|
315
|
+
contextuate monitor start --foreground # Run in foreground (blocking)
|
|
316
|
+
|
|
317
|
+
# Stop the monitor
|
|
318
|
+
contextuate monitor stop # Stop UI server only (daemon keeps running)
|
|
319
|
+
contextuate monitor stop --all # Stop both UI server and daemon
|
|
320
|
+
|
|
321
|
+
# Check status
|
|
322
|
+
contextuate monitor status
|
|
323
|
+
|
|
324
|
+
# Daemon management (advanced)
|
|
325
|
+
contextuate monitor daemon start # Start daemon only
|
|
326
|
+
contextuate monitor daemon start --detach # Start daemon in background
|
|
327
|
+
contextuate monitor daemon stop # Stop daemon
|
|
328
|
+
contextuate monitor daemon status # Check daemon status
|
|
329
|
+
contextuate monitor daemon logs # View daemon logs
|
|
330
|
+
contextuate monitor daemon logs -f # Follow daemon logs
|
|
331
|
+
contextuate monitor daemon logs -n 100 # Show last 100 lines
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
#### Configuration
|
|
335
|
+
|
|
336
|
+
Configuration is stored in `~/.contextuate/monitor/config.json`. Run `contextuate monitor init` for interactive setup, or edit the file directly.
|
|
337
|
+
|
|
338
|
+
##### Full Configuration Example
|
|
339
|
+
|
|
340
|
+
```json
|
|
341
|
+
{
|
|
342
|
+
"mode": "local",
|
|
343
|
+
"server": {
|
|
344
|
+
"host": "0.0.0.0",
|
|
345
|
+
"port": 3847,
|
|
346
|
+
"wsPort": 3848
|
|
347
|
+
},
|
|
348
|
+
"redis": {
|
|
349
|
+
"host": "localhost",
|
|
350
|
+
"port": 6379,
|
|
351
|
+
"password": null,
|
|
352
|
+
"channel": "contextuate:events"
|
|
353
|
+
},
|
|
354
|
+
"persistence": {
|
|
355
|
+
"enabled": true,
|
|
356
|
+
"type": "file",
|
|
357
|
+
"database": {
|
|
358
|
+
"host": "localhost",
|
|
359
|
+
"port": 3306,
|
|
360
|
+
"database": "contextuate",
|
|
361
|
+
"user": "contextuate",
|
|
362
|
+
"password": "secret"
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
"socketPath": "/tmp/contextuate-monitor.sock"
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
##### Configuration Parameters
|
|
370
|
+
|
|
371
|
+
| Parameter | Type | Default | Description |
|
|
372
|
+
|:----------|:-----|:--------|:------------|
|
|
373
|
+
| `mode` | `"local"` \| `"redis"` | `"local"` | Communication mode between components |
|
|
374
|
+
| `socketPath` | string | `"/tmp/contextuate-monitor.sock"` | Unix socket path (local mode only) |
|
|
375
|
+
|
|
376
|
+
**Server Settings** (`server`):
|
|
377
|
+
|
|
378
|
+
| Parameter | Type | Default | Description |
|
|
379
|
+
|:----------|:-----|:--------|:------------|
|
|
380
|
+
| `host` | string | `"0.0.0.0"` | Host to bind the HTTP server |
|
|
381
|
+
| `port` | number | `3847` | HTTP port for the dashboard |
|
|
382
|
+
| `wsPort` | number | `3848` | WebSocket port for real-time updates |
|
|
383
|
+
|
|
384
|
+
**Redis Settings** (`redis`) - for distributed/multi-machine setups:
|
|
385
|
+
|
|
386
|
+
| Parameter | Type | Default | Description |
|
|
387
|
+
|:----------|:-----|:--------|:------------|
|
|
388
|
+
| `host` | string | `"localhost"` | Redis server host |
|
|
389
|
+
| `port` | number | `6379` | Redis server port |
|
|
390
|
+
| `password` | string \| null | `null` | Redis password (optional) |
|
|
391
|
+
| `channel` | string | `"contextuate:events"` | Redis pub/sub channel name |
|
|
392
|
+
|
|
393
|
+
**Persistence Settings** (`persistence`):
|
|
394
|
+
|
|
395
|
+
| Parameter | Type | Default | Description |
|
|
396
|
+
|:----------|:-----|:--------|:------------|
|
|
397
|
+
| `enabled` | boolean | `true` | Enable session persistence |
|
|
398
|
+
| `type` | `"file"` \| `"mysql"` \| `"postgresql"` | `"file"` | Storage backend |
|
|
399
|
+
| `database` | object | - | Database connection settings (required for mysql/postgresql) |
|
|
400
|
+
|
|
401
|
+
**Database Settings** (`persistence.database`) - for MySQL/PostgreSQL:
|
|
402
|
+
|
|
403
|
+
| Parameter | Type | Description |
|
|
404
|
+
|:----------|:-----|:------------|
|
|
405
|
+
| `host` | string | Database server host |
|
|
406
|
+
| `port` | number | Database server port (3306 for MySQL, 5432 for PostgreSQL) |
|
|
407
|
+
| `database` | string | Database name |
|
|
408
|
+
| `user` | string | Database username |
|
|
409
|
+
| `password` | string | Database password |
|
|
410
|
+
|
|
411
|
+
> **Note:** MySQL and PostgreSQL persistence are planned features. Currently only file-based persistence is fully implemented.
|
|
412
|
+
|
|
413
|
+
##### Mode Comparison
|
|
414
|
+
|
|
415
|
+
| Feature | Local Mode | Redis Mode |
|
|
416
|
+
|:--------|:-----------|:-----------|
|
|
417
|
+
| Setup complexity | Simple | Requires Redis server |
|
|
418
|
+
| Multi-machine support | No | Yes |
|
|
419
|
+
| Single machine | Recommended | Overkill |
|
|
420
|
+
| Event delivery | Unix socket | Redis pub/sub |
|
|
421
|
+
| Use case | Personal development | Team/distributed environments |
|
|
422
|
+
|
|
423
|
+
#### Files and Directories
|
|
424
|
+
|
|
425
|
+
```
|
|
426
|
+
~/.contextuate/monitor/
|
|
427
|
+
├── config.json # Monitor configuration
|
|
428
|
+
├── sessions/ # Persisted session data
|
|
429
|
+
├── raw/ # Raw event files from hooks
|
|
430
|
+
├── processed/ # Processed event files
|
|
431
|
+
├── hooks/ # Hook scripts
|
|
432
|
+
├── daemon.pid # Daemon process ID
|
|
433
|
+
├── daemon.log # Daemon logs
|
|
434
|
+
├── server.pid # UI server process ID
|
|
435
|
+
└── server.log # UI server logs
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
272
440
|
## Documentation
|
|
273
441
|
|
|
274
442
|
For full documentation, see [contextuate.md](https://contextuate.md) or browse the `docs/ai/.contextuate/` directory.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Wrapper Command
|
|
3
|
+
*
|
|
4
|
+
* Spawns a Claude session managed by the daemon.
|
|
5
|
+
* The daemon handles PTY management, so the session persists
|
|
6
|
+
* even after this command exits.
|
|
7
|
+
*
|
|
8
|
+
* Usage: contextuate claude [claude-args...]
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Main command entry point
|
|
12
|
+
*/
|
|
13
|
+
export declare function claudeCommand(args: string[]): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* List active wrappers
|
|
16
|
+
*/
|
|
17
|
+
export declare function listWrappersCommand(): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Kill a wrapper session
|
|
20
|
+
*/
|
|
21
|
+
export declare function killWrapperCommand(wrapperId: string): Promise<void>;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Claude Wrapper Command
|
|
4
|
+
*
|
|
5
|
+
* Spawns a Claude session managed by the daemon.
|
|
6
|
+
* The daemon handles PTY management, so the session persists
|
|
7
|
+
* even after this command exits.
|
|
8
|
+
*
|
|
9
|
+
* Usage: contextuate claude [claude-args...]
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.claudeCommand = claudeCommand;
|
|
46
|
+
exports.listWrappersCommand = listWrappersCommand;
|
|
47
|
+
exports.killWrapperCommand = killWrapperCommand;
|
|
48
|
+
const net = __importStar(require("net"));
|
|
49
|
+
const fs = __importStar(require("fs"));
|
|
50
|
+
// Daemon socket path
|
|
51
|
+
const DAEMON_SOCKET = '/tmp/contextuate-daemon.sock';
|
|
52
|
+
/**
|
|
53
|
+
* Connect to daemon and spawn a wrapper
|
|
54
|
+
*/
|
|
55
|
+
async function spawnWrapper(args, cwd) {
|
|
56
|
+
return new Promise((resolve) => {
|
|
57
|
+
// Check if daemon socket exists
|
|
58
|
+
if (!fs.existsSync(DAEMON_SOCKET)) {
|
|
59
|
+
resolve({ success: false, error: 'Daemon not running. Start with: contextuate monitor' });
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const socket = new net.Socket();
|
|
63
|
+
let responseReceived = false;
|
|
64
|
+
socket.connect(DAEMON_SOCKET, () => {
|
|
65
|
+
// Send spawn request
|
|
66
|
+
const message = {
|
|
67
|
+
type: 'spawn_wrapper',
|
|
68
|
+
args,
|
|
69
|
+
cwd,
|
|
70
|
+
cols: process.stdout.columns || 120,
|
|
71
|
+
rows: process.stdout.rows || 40,
|
|
72
|
+
};
|
|
73
|
+
socket.write(JSON.stringify(message) + '\n');
|
|
74
|
+
});
|
|
75
|
+
socket.on('data', (data) => {
|
|
76
|
+
try {
|
|
77
|
+
const lines = data.toString().split('\n').filter(l => l.trim());
|
|
78
|
+
for (const line of lines) {
|
|
79
|
+
const response = JSON.parse(line);
|
|
80
|
+
if (response.type === 'wrapper_spawned') {
|
|
81
|
+
responseReceived = true;
|
|
82
|
+
socket.end();
|
|
83
|
+
resolve({
|
|
84
|
+
success: response.success,
|
|
85
|
+
wrapperId: response.wrapperId,
|
|
86
|
+
error: response.error,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
// Ignore parse errors
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
socket.on('error', (err) => {
|
|
96
|
+
if (!responseReceived) {
|
|
97
|
+
resolve({ success: false, error: `Connection error: ${err.message}` });
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
socket.on('close', () => {
|
|
101
|
+
if (!responseReceived) {
|
|
102
|
+
resolve({ success: false, error: 'Connection closed without response' });
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
// Timeout after 10 seconds
|
|
106
|
+
setTimeout(() => {
|
|
107
|
+
if (!responseReceived) {
|
|
108
|
+
socket.destroy();
|
|
109
|
+
resolve({ success: false, error: 'Spawn request timed out' });
|
|
110
|
+
}
|
|
111
|
+
}, 10000);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Main command entry point
|
|
116
|
+
*/
|
|
117
|
+
async function claudeCommand(args) {
|
|
118
|
+
const cwd = process.cwd();
|
|
119
|
+
console.log('Spawning Claude session via daemon...');
|
|
120
|
+
const result = await spawnWrapper(args, cwd);
|
|
121
|
+
if (result.success) {
|
|
122
|
+
console.log(`\nClaude session started: ${result.wrapperId}`);
|
|
123
|
+
console.log('\nThe session is now running in the background, managed by the daemon.');
|
|
124
|
+
console.log('Access it via the monitor UI at http://localhost:3456');
|
|
125
|
+
console.log('\nTo view active wrappers: contextuate wrapper list');
|
|
126
|
+
console.log('To kill a wrapper: contextuate wrapper kill <wrapper-id>');
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
console.error(`\nFailed to spawn Claude session: ${result.error}`);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* List active wrappers
|
|
135
|
+
*/
|
|
136
|
+
async function listWrappersCommand() {
|
|
137
|
+
return new Promise((resolve) => {
|
|
138
|
+
if (!fs.existsSync(DAEMON_SOCKET)) {
|
|
139
|
+
console.error('Daemon not running. Start with: contextuate monitor');
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
const socket = new net.Socket();
|
|
143
|
+
socket.connect(DAEMON_SOCKET, () => {
|
|
144
|
+
socket.write(JSON.stringify({ type: 'get_wrappers' }) + '\n');
|
|
145
|
+
});
|
|
146
|
+
socket.on('data', (data) => {
|
|
147
|
+
try {
|
|
148
|
+
const lines = data.toString().split('\n').filter(l => l.trim());
|
|
149
|
+
for (const line of lines) {
|
|
150
|
+
const response = JSON.parse(line);
|
|
151
|
+
if (response.type === 'wrappers_list') {
|
|
152
|
+
socket.end();
|
|
153
|
+
if (response.wrappers.length === 0) {
|
|
154
|
+
console.log('No active wrapper sessions.');
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
console.log('Active wrapper sessions:\n');
|
|
158
|
+
for (const wrapper of response.wrappers) {
|
|
159
|
+
const type = wrapper.managed ? 'managed' : 'legacy';
|
|
160
|
+
console.log(` ${wrapper.wrapperId} [${type}]`);
|
|
161
|
+
console.log(` State: ${wrapper.state}`);
|
|
162
|
+
console.log(` PID: ${wrapper.pid}`);
|
|
163
|
+
console.log(` CWD: ${wrapper.cwd}`);
|
|
164
|
+
if (wrapper.claudeSessionId) {
|
|
165
|
+
console.log(` Claude Session: ${wrapper.claudeSessionId.slice(0, 8)}...`);
|
|
166
|
+
}
|
|
167
|
+
console.log();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
resolve();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
// Ignore parse errors
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
socket.on('error', (err) => {
|
|
179
|
+
console.error(`Connection error: ${err.message}`);
|
|
180
|
+
process.exit(1);
|
|
181
|
+
});
|
|
182
|
+
setTimeout(() => {
|
|
183
|
+
socket.destroy();
|
|
184
|
+
console.error('Request timed out');
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}, 5000);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Kill a wrapper session
|
|
191
|
+
*/
|
|
192
|
+
async function killWrapperCommand(wrapperId) {
|
|
193
|
+
return new Promise((resolve) => {
|
|
194
|
+
if (!fs.existsSync(DAEMON_SOCKET)) {
|
|
195
|
+
console.error('Daemon not running. Start with: contextuate monitor');
|
|
196
|
+
process.exit(1);
|
|
197
|
+
}
|
|
198
|
+
const socket = new net.Socket();
|
|
199
|
+
socket.connect(DAEMON_SOCKET, () => {
|
|
200
|
+
socket.write(JSON.stringify({ type: 'kill_wrapper', wrapperId }) + '\n');
|
|
201
|
+
// Give daemon time to process, then close
|
|
202
|
+
setTimeout(() => {
|
|
203
|
+
socket.end();
|
|
204
|
+
console.log(`Kill request sent for wrapper ${wrapperId}`);
|
|
205
|
+
resolve();
|
|
206
|
+
}, 500);
|
|
207
|
+
});
|
|
208
|
+
socket.on('error', (err) => {
|
|
209
|
+
console.error(`Connection error: ${err.message}`);
|
|
210
|
+
process.exit(1);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function addContextCommand(): Promise<void>;
|
package/dist/commands/init.js
CHANGED
|
@@ -8,6 +8,37 @@ const inquirer_1 = __importDefault(require("inquirer"));
|
|
|
8
8
|
const chalk_1 = __importDefault(require("chalk"));
|
|
9
9
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
10
10
|
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const fs_1 = require("fs");
|
|
12
|
+
// Get package version dynamically
|
|
13
|
+
function getPackageVersion() {
|
|
14
|
+
try {
|
|
15
|
+
const packageJson = JSON.parse((0, fs_1.readFileSync)(path_1.default.join(__dirname, '../../package.json'), 'utf-8'));
|
|
16
|
+
return packageJson.version;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return '0.0.0';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// Get package info for version.json
|
|
23
|
+
function getPackageInfo() {
|
|
24
|
+
try {
|
|
25
|
+
const packageJson = JSON.parse((0, fs_1.readFileSync)(path_1.default.join(__dirname, '../../package.json'), 'utf-8'));
|
|
26
|
+
return {
|
|
27
|
+
name: packageJson.name || 'contextuate',
|
|
28
|
+
version: packageJson.version || '0.0.0',
|
|
29
|
+
description: packageJson.description || 'AI Context Framework',
|
|
30
|
+
repository: packageJson.repository?.url?.replace('git+', '').replace('.git', '') || 'https://github.com/esotech/contextuate'
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return {
|
|
35
|
+
name: 'contextuate',
|
|
36
|
+
version: '0.0.0',
|
|
37
|
+
description: 'AI Context Framework',
|
|
38
|
+
repository: 'https://github.com/esotech/contextuate'
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
11
42
|
// Platform definitions with metadata
|
|
12
43
|
const PLATFORMS = [
|
|
13
44
|
{ id: 'agents', name: 'Agents.ai', src: 'templates/platforms/AGENTS.md', dest: 'AGENTS.md' },
|
|
@@ -57,7 +88,7 @@ async function initCommand(platformArgs, options) {
|
|
|
57
88
|
console.log(chalk_1.default.blue('╔════════════════════════════════════════╗'));
|
|
58
89
|
console.log(chalk_1.default.blue('║ Contextuate Installer ║'));
|
|
59
90
|
console.log(chalk_1.default.blue('║ AI Context Framework ║'));
|
|
60
|
-
console.log(chalk_1.default.blue('║
|
|
91
|
+
console.log(chalk_1.default.blue('║ ║'));
|
|
61
92
|
console.log(chalk_1.default.blue('╚════════════════════════════════════════╝'));
|
|
62
93
|
console.log('');
|
|
63
94
|
try {
|
|
@@ -168,7 +199,11 @@ async function initCommand(platformArgs, options) {
|
|
|
168
199
|
}
|
|
169
200
|
if (opts.agents && opts.agents.length > 0) {
|
|
170
201
|
// Non-interactive agent selection via --agents flag
|
|
171
|
-
if (opts.agents.includes('
|
|
202
|
+
if (opts.agents.includes('none')) {
|
|
203
|
+
// Explicitly skip agent installation
|
|
204
|
+
console.log(chalk_1.default.blue('[INFO] Skipping agent installation (--agents none)'));
|
|
205
|
+
}
|
|
206
|
+
else if (opts.agents.includes('all')) {
|
|
172
207
|
selectedAgents = availableAgents;
|
|
173
208
|
console.log(chalk_1.default.blue('[INFO] Installing all agents'));
|
|
174
209
|
}
|
|
@@ -185,7 +220,7 @@ async function initCommand(platformArgs, options) {
|
|
|
185
220
|
console.log(chalk_1.default.yellow(`[WARN] Could not match agent "${agentArg}" - skipping`));
|
|
186
221
|
}
|
|
187
222
|
}
|
|
188
|
-
if (selectedAgents.length === 0 && opts.agents.length > 0
|
|
223
|
+
if (selectedAgents.length === 0 && opts.agents.length > 0) {
|
|
189
224
|
console.log(chalk_1.default.yellow('[WARN] No valid agents matched. Available agents:'));
|
|
190
225
|
availableAgents.forEach(a => console.log(` - ${a}`));
|
|
191
226
|
}
|
|
@@ -226,6 +261,11 @@ async function initCommand(platformArgs, options) {
|
|
|
226
261
|
}
|
|
227
262
|
}
|
|
228
263
|
}
|
|
264
|
+
else {
|
|
265
|
+
// Non-interactive mode without --agents flag: default to all agents
|
|
266
|
+
selectedAgents = availableAgents;
|
|
267
|
+
console.log(chalk_1.default.blue('[INFO] Installing all agents (default in non-interactive mode)'));
|
|
268
|
+
}
|
|
229
269
|
console.log('');
|
|
230
270
|
console.log(chalk_1.default.blue('[INFO] Installing Contextuate framework...'));
|
|
231
271
|
console.log('');
|
|
@@ -301,7 +341,18 @@ async function initCommand(platformArgs, options) {
|
|
|
301
341
|
console.log(chalk_1.default.green(`[OK] Created: ${dest}`));
|
|
302
342
|
};
|
|
303
343
|
// Copy core engine files only to .contextuate
|
|
304
|
-
|
|
344
|
+
// Generate version.json dynamically from package.json
|
|
345
|
+
const pkgInfo = getPackageInfo();
|
|
346
|
+
const versionData = {
|
|
347
|
+
name: pkgInfo.name,
|
|
348
|
+
version: pkgInfo.version,
|
|
349
|
+
description: pkgInfo.description,
|
|
350
|
+
repository: pkgInfo.repository,
|
|
351
|
+
installed: new Date().toISOString(),
|
|
352
|
+
updated: new Date().toISOString()
|
|
353
|
+
};
|
|
354
|
+
await fs_extra_1.default.writeFile(path_1.default.join(installDir, 'version.json'), JSON.stringify(versionData, null, 2));
|
|
355
|
+
console.log(chalk_1.default.green(`[OK] Created: ${path_1.default.join(installDir, 'version.json')}`));
|
|
305
356
|
await copyFile(path_1.default.join(templateSource, 'README.md'), path_1.default.join(installDir, 'README.md'));
|
|
306
357
|
// Copy directories - only core framework files
|
|
307
358
|
const copyDirContents = async (srcSubDir, destDir) => {
|
|
@@ -337,7 +388,14 @@ async function initCommand(platformArgs, options) {
|
|
|
337
388
|
// Copy contextuate.md (main entry point) directly from templates to docs/ai/.contextuate/ (protected)
|
|
338
389
|
await copyFile(path_1.default.join(templateSource, 'templates/contextuate.md'), 'docs/ai/.contextuate/contextuate.md');
|
|
339
390
|
// Copy context.md (user customizable) directly from templates to docs/ai/
|
|
340
|
-
|
|
391
|
+
// IMPORTANT: Never overwrite context.md even with --force, as it contains project-specific context
|
|
392
|
+
const contextMdPath = 'docs/ai/context.md';
|
|
393
|
+
if (fs_extra_1.default.existsSync(contextMdPath)) {
|
|
394
|
+
console.log(chalk_1.default.yellow(`[WARN] Preserved (project context): ${contextMdPath}`));
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
await copyFile(path_1.default.join(templateSource, 'templates/context.md'), contextMdPath);
|
|
398
|
+
}
|
|
341
399
|
console.log('');
|
|
342
400
|
// 5. Generate jump files for selected platforms
|
|
343
401
|
console.log(chalk_1.default.blue('[INFO] Generating platform jump files...'));
|
|
@@ -391,6 +449,9 @@ async function initCommand(platformArgs, options) {
|
|
|
391
449
|
{ target: 'docs/ai/agents', link: '.claude/agents' },
|
|
392
450
|
{ target: 'docs/ai/hooks', link: '.claude/hooks' },
|
|
393
451
|
{ target: 'docs/ai/skills', link: '.claude/skills' },
|
|
452
|
+
// Link .contextuate so relative paths from agents work correctly
|
|
453
|
+
// (e.g., ../.contextuate/agents/base.md resolves properly)
|
|
454
|
+
{ target: 'docs/ai/.contextuate', link: '.claude/.contextuate' },
|
|
394
455
|
];
|
|
395
456
|
for (const symlink of symlinks) {
|
|
396
457
|
await createSymlink(symlink.target, symlink.link);
|
|
@@ -429,7 +490,7 @@ async function initCommand(platformArgs, options) {
|
|
|
429
490
|
console.log('');
|
|
430
491
|
console.log('Documentation: https://contextuate.md');
|
|
431
492
|
console.log('');
|
|
432
|
-
console.log(chalk_1.default.gray('
|
|
493
|
+
console.log(chalk_1.default.gray('Contextuate Framework'));
|
|
433
494
|
console.log(chalk_1.default.gray('Created by Alexander Conroy (@geilt)'));
|
|
434
495
|
console.log('');
|
|
435
496
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
interface InstallOptions {
|
|
2
|
+
agents?: string[];
|
|
3
|
+
standards?: string[];
|
|
4
|
+
tools?: string[];
|
|
5
|
+
skills?: string[];
|
|
6
|
+
all?: boolean;
|
|
7
|
+
list?: boolean;
|
|
8
|
+
force?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function installAgentsCommand(names: string[], options: {
|
|
11
|
+
all?: boolean;
|
|
12
|
+
force?: boolean;
|
|
13
|
+
includeSkills?: boolean;
|
|
14
|
+
}): Promise<void>;
|
|
15
|
+
export declare function installStandardsCommand(names: string[], options: {
|
|
16
|
+
all?: boolean;
|
|
17
|
+
force?: boolean;
|
|
18
|
+
}): Promise<void>;
|
|
19
|
+
export declare function installToolsCommand(names: string[], options: {
|
|
20
|
+
all?: boolean;
|
|
21
|
+
force?: boolean;
|
|
22
|
+
}): Promise<void>;
|
|
23
|
+
export declare function installSkillsCommand(names: string[], options: {
|
|
24
|
+
all?: boolean;
|
|
25
|
+
force?: boolean;
|
|
26
|
+
}): Promise<void>;
|
|
27
|
+
export declare function installCommand(options: InstallOptions): Promise<void>;
|
|
28
|
+
export {};
|