@dmsdc-ai/aigentry-telepty 0.3.3 → 0.4.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/CHANGELOG.md +182 -0
- package/README.md +67 -1
- package/cli.js +161 -54
- package/cross-machine.js +132 -0
- package/daemon.js +355 -5
- package/host-spec.js +60 -0
- package/mcp-server/index.mjs +24 -3
- package/package.json +30 -5
- package/session-state.js +23 -0
- package/skill-installer.js +42 -6
- package/skills/telepty/SKILL.md +1 -1
- package/skills/telepty-allow/SKILL.md +1 -1
- package/skills/telepty-attach/SKILL.md +1 -1
- package/skills/telepty-broadcast/SKILL.md +1 -1
- package/skills/telepty-daemon/SKILL.md +1 -1
- package/skills/telepty-inject/SKILL.md +76 -4
- package/skills/telepty-list/SKILL.md +1 -1
- package/skills/telepty-listen/SKILL.md +1 -1
- package/skills/telepty-rename/SKILL.md +1 -1
- package/skills/telepty-session/SKILL.md +1 -1
- package/src/init/print-snippet.js +114 -0
- package/src/init/snippets/agents.md +15 -0
- package/src/init/snippets/claude.md +15 -0
- package/src/init/snippets/gemini.md +15 -0
- package/src/prompt-symbol-registry.js +43 -1
- package/.claude/commands/telepty-allow.md +0 -58
- package/.claude/commands/telepty-attach.md +0 -22
- package/.claude/commands/telepty-inject.md +0 -72
- package/.claude/commands/telepty-list.md +0 -22
- package/.claude/commands/telepty-manual-test.md +0 -73
- package/.claude/commands/telepty-start.md +0 -25
- package/.claude/commands/telepty-test.md +0 -25
- package/.claude/commands/telepty.md +0 -82
- package/AGENTS.md +0 -74
- package/BOUNDARY.md +0 -31
- package/BUS_EVENT_SCHEMA.md +0 -206
- package/CLAUDE.md +0 -100
- package/GEMINI.md +0 -10
- package/URGENT_ISSUES.resolved.md +0 -1
- package/docs/superpowers/specs/2026-04-26-inject-submit-enter-reliability.md +0 -447
- package/docs/superpowers/specs/2026-04-26-prompt-symbol-render-gate.md +0 -571
- package/docs/superpowers/specs/2026-04-26-submit-gate-fixes-v2.md +0 -608
- package/docs/superpowers/specs/2026-05-02-submit-force-and-retry.md +0 -139
- package/protocol/mailbox.md +0 -244
- package/specs/codex-inject-spec.md +0 -201
- package/specs/enforce-report-spec.md +0 -237
- package/templates/AGENTS.md +0 -71
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
# telepty-manual-test
|
|
2
|
-
|
|
3
|
-
Guided manual test of the telepty enable (inject) feature. Runs step-by-step verification.
|
|
4
|
-
|
|
5
|
-
## Instructions
|
|
6
|
-
|
|
7
|
-
Execute each step sequentially, verifying results before proceeding.
|
|
8
|
-
|
|
9
|
-
### Step 1: Ensure daemon is running
|
|
10
|
-
```bash
|
|
11
|
-
cd /Users/duckyoungkim/projects/aigentry-telepty
|
|
12
|
-
curl -s http://127.0.0.1:3848/api/sessions 2>/dev/null || node daemon.js &
|
|
13
|
-
sleep 1
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
### Step 2: Register a wrapped session via API
|
|
17
|
-
```bash
|
|
18
|
-
TOKEN=$(cat ~/.telepty/config.json 2>/dev/null | grep authToken | cut -d '"' -f 4)
|
|
19
|
-
curl -s -X POST http://127.0.0.1:3848/api/sessions/register \
|
|
20
|
-
-H "Content-Type: application/json" \
|
|
21
|
-
-H "x-telepty-token: $TOKEN" \
|
|
22
|
-
-d '{"session_id": "manual-test-1", "command": "test", "cwd": "'"$(pwd)"'"}'
|
|
23
|
-
```
|
|
24
|
-
**Verify**: response has `type: "wrapped"` and status 201.
|
|
25
|
-
|
|
26
|
-
### Step 3: Check session listing
|
|
27
|
-
```bash
|
|
28
|
-
curl -s http://127.0.0.1:3848/api/sessions -H "x-telepty-token: $TOKEN" | python3 -m json.tool
|
|
29
|
-
```
|
|
30
|
-
**Verify**: `manual-test-1` appears with `type: "wrapped"`.
|
|
31
|
-
|
|
32
|
-
### Step 4: Test inject without owner (should fail)
|
|
33
|
-
```bash
|
|
34
|
-
curl -s -X POST http://127.0.0.1:3848/api/sessions/manual-test-1/inject \
|
|
35
|
-
-H "Content-Type: application/json" \
|
|
36
|
-
-H "x-telepty-token: $TOKEN" \
|
|
37
|
-
-d '{"prompt": "hello"}'
|
|
38
|
-
```
|
|
39
|
-
**Verify**: returns 503 with "not connected" error.
|
|
40
|
-
|
|
41
|
-
### Step 5: Clean up test session
|
|
42
|
-
```bash
|
|
43
|
-
curl -s -X DELETE http://127.0.0.1:3848/api/sessions/manual-test-1 \
|
|
44
|
-
-H "x-telepty-token: $TOKEN"
|
|
45
|
-
```
|
|
46
|
-
**Verify**: returns status "closing".
|
|
47
|
-
|
|
48
|
-
### Step 6: Verify session removed
|
|
49
|
-
```bash
|
|
50
|
-
curl -s http://127.0.0.1:3848/api/sessions -H "x-telepty-token: $TOKEN"
|
|
51
|
-
```
|
|
52
|
-
**Verify**: `manual-test-1` no longer in the list.
|
|
53
|
-
|
|
54
|
-
### Step 7: Run automated tests
|
|
55
|
-
```bash
|
|
56
|
-
npm test
|
|
57
|
-
```
|
|
58
|
-
**Verify**: all 25 tests pass.
|
|
59
|
-
|
|
60
|
-
### Report
|
|
61
|
-
Summarize all verification results in a table:
|
|
62
|
-
|
|
63
|
-
| Step | Check | Result |
|
|
64
|
-
|------|-------|--------|
|
|
65
|
-
| 2 | Register returns 201 + wrapped | ? |
|
|
66
|
-
| 3 | Session in list with type | ? |
|
|
67
|
-
| 4 | Inject without owner = 503 | ? |
|
|
68
|
-
| 5 | DELETE returns closing | ? |
|
|
69
|
-
| 6 | Session removed | ? |
|
|
70
|
-
| 7 | All tests pass | ? |
|
|
71
|
-
|
|
72
|
-
## Arguments
|
|
73
|
-
- `$ARGUMENTS`: ignored
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# telepty-start
|
|
2
|
-
|
|
3
|
-
Start the telepty daemon process.
|
|
4
|
-
|
|
5
|
-
## Instructions
|
|
6
|
-
|
|
7
|
-
1. Check if daemon is already running:
|
|
8
|
-
```bash
|
|
9
|
-
curl -s http://127.0.0.1:3848/api/sessions 2>/dev/null && echo "RUNNING" || echo "NOT RUNNING"
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
2. If not running, start it:
|
|
13
|
-
```bash
|
|
14
|
-
cd /Users/duckyoungkim/projects/aigentry-telepty && node daemon.js &
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
3. Verify it started:
|
|
18
|
-
```bash
|
|
19
|
-
sleep 1 && curl -s http://127.0.0.1:3848/api/sessions
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
4. Report status.
|
|
23
|
-
|
|
24
|
-
## Arguments
|
|
25
|
-
- `$ARGUMENTS`: optional port override (e.g., "3849")
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# telepty-test
|
|
2
|
-
|
|
3
|
-
Run the telepty automated test suite and report results.
|
|
4
|
-
|
|
5
|
-
## Instructions
|
|
6
|
-
|
|
7
|
-
1. Run the full test suite:
|
|
8
|
-
```bash
|
|
9
|
-
cd /Users/duckyoungkim/projects/aigentry-telepty && npm test
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
2. Parse the output and report:
|
|
13
|
-
- Total tests, passed, failed
|
|
14
|
-
- If any failures: show the failing test name and error message
|
|
15
|
-
- If all pass: confirm with count
|
|
16
|
-
|
|
17
|
-
3. If tests fail, investigate:
|
|
18
|
-
- Read the failing test in `test/daemon.test.js`
|
|
19
|
-
- Check if daemon.js has related issues
|
|
20
|
-
- Suggest or apply fixes
|
|
21
|
-
- Re-run tests to confirm
|
|
22
|
-
|
|
23
|
-
## Arguments
|
|
24
|
-
- No arguments: run all tests
|
|
25
|
-
- `$ARGUMENTS`: if provided, use as a grep filter to run specific tests (e.g., "wrap", "register", "inject")
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
# telepty
|
|
2
|
-
|
|
3
|
-
Help the user interact with the `telepty` daemon — check session IDs, list active sessions, inject commands, send bus events, and manage terminal windows.
|
|
4
|
-
|
|
5
|
-
## Trigger
|
|
6
|
-
|
|
7
|
-
When the user asks about their current session ID, wants to check/list active sessions, inject a prompt into a session, send a JSON event via the bus, subscribe to the bus, rename a session, or update telepty.
|
|
8
|
-
|
|
9
|
-
## Instructions
|
|
10
|
-
|
|
11
|
-
### 1. Check Current Session ID
|
|
12
|
-
- Run: `echo $TELEPTY_SESSION_ID`
|
|
13
|
-
- If empty: this shell is NOT inside a telepty session.
|
|
14
|
-
- If set: display it. This is the ID other agents use to target this session.
|
|
15
|
-
|
|
16
|
-
### 2. List All Sessions
|
|
17
|
-
- Run: `telepty list`
|
|
18
|
-
|
|
19
|
-
### 3. Send a Message to Another Agent
|
|
20
|
-
Choose ONE of three methods based on intent:
|
|
21
|
-
|
|
22
|
-
**Method A: Prompt Injection (Active Interruption)**
|
|
23
|
-
The receiving AI will IMMEDIATELY read and execute the message as a prompt.
|
|
24
|
-
```bash
|
|
25
|
-
telepty inject <target_session_id> "<prompt text>"
|
|
26
|
-
```
|
|
27
|
-
For multiple targets: `telepty multicast <id1>,<id2> "<prompt>"`
|
|
28
|
-
|
|
29
|
-
**Method B: Log Injection (Visual Notification)**
|
|
30
|
-
The message appears on the receiving terminal screen for the user to see, but the AI does NOT execute it as a prompt.
|
|
31
|
-
```bash
|
|
32
|
-
telepty inject <target_session_id> "echo '\x1b[33m[Message from $TELEPTY_SESSION_ID]\x1b[0m <message text>'"
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
**Method C: Background JSON Bus (Passive/Silent)**
|
|
36
|
-
Structured data transfer that won't disturb the receiving terminal screen.
|
|
37
|
-
```bash
|
|
38
|
-
TOKEN=$(cat ~/.telepty/config.json | grep authToken | cut -d '"' -f 4)
|
|
39
|
-
curl -s -X POST http://127.0.0.1:3848/api/bus/publish \
|
|
40
|
-
-H "Content-Type: application/json" \
|
|
41
|
-
-H "x-telepty-token: $TOKEN" \
|
|
42
|
-
-d '{"type": "bg_message", "payload": "..."}'
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
### 4. Subscribe to the Event Bus
|
|
46
|
-
```bash
|
|
47
|
-
nohup telepty listen > .telepty_bus_events.log 2>&1 &
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### 5. Open a New Ghostty Terminal Window
|
|
51
|
-
Physically spawn a new terminal window already attached to a telepty session:
|
|
52
|
-
```bash
|
|
53
|
-
cat << 'EOF' > /tmp/telepty-auto.command
|
|
54
|
-
#!/bin/bash
|
|
55
|
-
telepty spawn --id <ID> <CMD>
|
|
56
|
-
EOF
|
|
57
|
-
chmod +x /tmp/telepty-auto.command
|
|
58
|
-
open -a Ghostty /tmp/telepty-auto.command || open /tmp/telepty-auto.command
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### 6. Terminal Title Convention
|
|
62
|
-
Each telepty session displays its ID in the Ghostty tab title:
|
|
63
|
-
- Local: `⚡ telepty :: {session_id}`
|
|
64
|
-
- Remote: `⚡ telepty :: {session_id} @ {host}`
|
|
65
|
-
|
|
66
|
-
### 7. Allow Inject on a CLI
|
|
67
|
-
Run any command with inject allowed:
|
|
68
|
-
```bash
|
|
69
|
-
# With custom session ID
|
|
70
|
-
telepty allow --id my-claude -- claude
|
|
71
|
-
telepty allow --id codex-main -- codex
|
|
72
|
-
telepty allow --id gemini-1 -- gemini
|
|
73
|
-
|
|
74
|
-
# Auto-generated session ID
|
|
75
|
-
telepty allow -- bash
|
|
76
|
-
```
|
|
77
|
-
The process runs locally (isTTY preserved), but registers with the daemon so inject works.
|
|
78
|
-
|
|
79
|
-
### 8. Update
|
|
80
|
-
```bash
|
|
81
|
-
telepty update
|
|
82
|
-
```
|
package/AGENTS.md
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
# AGENTS.md — aigentry-telepty
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
PTY Multiplexer & Session Orchestrator — aigentry 에코시스템의 **통신 인프라**.
|
|
6
|
-
npm: `@dmsdc-ai/aigentry-telepty` | 멀티 AI 세션을 생성·연결·제어하는 PTY 멀티플렉서.
|
|
7
|
-
|
|
8
|
-
## Architecture
|
|
9
|
-
|
|
10
|
-
```
|
|
11
|
-
CLI (cli.js) ──→ HTTP/WS ──→ Daemon (daemon.js:3848)
|
|
12
|
-
├── Session WS (/api/sessions/:id)
|
|
13
|
-
├── Event Bus WS (/api/bus)
|
|
14
|
-
└── REST API (/api/sessions/*)
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
| 파일 | 역할 |
|
|
18
|
-
|------|------|
|
|
19
|
-
| `cli.js` | CLI 명령 + allow-bridge (PTY 래핑) |
|
|
20
|
-
| `daemon.js` | HTTP/WS 서버, 세션 상태, inject 전달 |
|
|
21
|
-
| `tui.js` | blessed 기반 TUI 대시보드 |
|
|
22
|
-
| `session-routing.js` | 세션 ID 해석, alias 매칭, 호스트 그룹핑 |
|
|
23
|
-
| `daemon-control.js` | 싱글톤 daemon PID 관리 |
|
|
24
|
-
| `auth.js` | UUID 토큰 기반 인증 |
|
|
25
|
-
| `interactive-terminal.js` | raw mode stdin/stdout 관리 |
|
|
26
|
-
| `skill-installer.js` | CLI별 스킬 설치 (Claude/Codex/Gemini) |
|
|
27
|
-
|
|
28
|
-
## Inject 전달 경로 (wrapped session)
|
|
29
|
-
|
|
30
|
-
1. **Primary**: `kitty @ send-text` (터미널 직접 전달, allow-bridge 우회)
|
|
31
|
-
2. **Fallback**: WS → allow-bridge → `child.write()` (PTY)
|
|
32
|
-
3. **Submit**: `osascript` Return 키 → kitty fallback → WS `\r`
|
|
33
|
-
|
|
34
|
-
busy 세션: CR은 큐에 대기 중인 텍스트와 함께 큐잉 후 올바른 순서로 flush.
|
|
35
|
-
|
|
36
|
-
## Commands
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
npm test # 43 tests (node:test)
|
|
40
|
-
telepty daemon # daemon 시작 (포트 3848)
|
|
41
|
-
telepty allow --id <name> claude # 세션 래핑
|
|
42
|
-
telepty tui # TUI 대시보드
|
|
43
|
-
telepty list # 세션 목록
|
|
44
|
-
telepty inject <id> "msg" # 메시지 주입
|
|
45
|
-
telepty broadcast "msg" # 전체 브로드캐스트
|
|
46
|
-
telepty session start --launch # kitty 탭으로 다중 세션 시작
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## Key Rules
|
|
50
|
-
|
|
51
|
-
- inject 후 submit은 항상 `osascript`로 통일 (`--no-enter` + osascript keystroke)
|
|
52
|
-
- inject 시 발신자 session ID (`--from`)를 항상 포함
|
|
53
|
-
- PTY `\r` 직접 의존 금지
|
|
54
|
-
|
|
55
|
-
## Session Communication
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
# List active sessions
|
|
59
|
-
telepty list
|
|
60
|
-
|
|
61
|
-
# Send message to another session
|
|
62
|
-
telepty inject --from aigentry-telepty-{cli} <target-session> "message"
|
|
63
|
-
|
|
64
|
-
# Report to orchestrator
|
|
65
|
-
telepty inject --ref --from aigentry-telepty-{cli} aigentry-orchestrator-claude "report"
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
## Work Principles
|
|
69
|
-
|
|
70
|
-
- **Best-First**: 항상 최선의 해결책 선택. 차선책/우회 금지.
|
|
71
|
-
- **Configurable**: 설정으로 제어 가능한 구조. 하드코딩 금지.
|
|
72
|
-
- **Evidence-Based**: 추측 금지. 데이터/로그/테스트 결과 기반 판단.
|
|
73
|
-
- **Fail Fast**: 에러 즉시 보고. 숨기지 않음.
|
|
74
|
-
- **Constitution**: ~/projects/aigentry/docs/CONSTITUTION.md 준수.
|
package/BOUNDARY.md
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# telepty Responsibility Boundary
|
|
2
|
-
|
|
3
|
-
## What telepty owns
|
|
4
|
-
|
|
5
|
-
- **PTY lifecycle**: spawn, resize, kill PTY processes; emit session_spawn / session_register / session_rename events
|
|
6
|
-
- **Raw stdin write**: accept inject requests and write bytes to the PTY fd (best-effort, fire-and-forget)
|
|
7
|
-
- **stdout streaming**: pipe PTY output to connected WebSocket clients in real time
|
|
8
|
-
- **Bus event broadcast**: publish structured events to all `/api/bus` subscribers
|
|
9
|
-
- **Session lifecycle**: track active sessions, clean up on exit or owner disconnect
|
|
10
|
-
- **Liveness heartbeat**: emit `session_health` every 10 seconds per active session
|
|
11
|
-
|
|
12
|
-
## What telepty does NOT own
|
|
13
|
-
|
|
14
|
-
- **CLI state management**: the caller owns its own state machine; telepty does not know what state an agent is in
|
|
15
|
-
- **Inject processing confirmation**: telepty emits `inject_written` when bytes are handed to the OS; it cannot confirm the process consumed or acted on them
|
|
16
|
-
- **Output parsing / interpretation**: telepty streams raw bytes; callers parse meaning
|
|
17
|
-
- **Message guarantee / retry / ordering**: no retry logic, no queue, no ordering guarantees across multiple injects
|
|
18
|
-
- **Session recovery / persistence**: sessions are in-memory; a daemon restart loses all sessions
|
|
19
|
-
- **Cross-session routing**: routing logic (which session gets which message) belongs to the caller or an orchestration layer above telepty
|
|
20
|
-
|
|
21
|
-
## PTY limitations
|
|
22
|
-
|
|
23
|
-
- `inject_written` is **best-effort**: it confirms the write syscall to the OS PTY fd succeeded, not that the running process read or processed the input
|
|
24
|
-
- The OS buffers stdin asynchronously; a process blocked, sleeping, or not reading stdin will silently queue the bytes
|
|
25
|
-
- There is no read-back or echo confirmation; callers must observe stdout via the WebSocket stream to infer processing
|
|
26
|
-
|
|
27
|
-
## Design principle
|
|
28
|
-
|
|
29
|
-
> **telepty = stateless dumb pipe**
|
|
30
|
-
|
|
31
|
-
telepty moves bytes. It does not interpret, retry, sequence, or guarantee delivery beyond the OS write call. All higher-level semantics (acknowledgement, ordering, state machines, recovery) are the responsibility of the layer above.
|
package/BUS_EVENT_SCHEMA.md
DELETED
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
# Telepty Bus Event Schema Standard
|
|
2
|
-
|
|
3
|
-
Version: 2.0 (2026-03-15)
|
|
4
|
-
Agreed by: telepty, deliberation, devkit, brain, orchestrator
|
|
5
|
-
|
|
6
|
-
## Transport
|
|
7
|
-
|
|
8
|
-
- **HTTP**: `POST /api/bus/publish` with JSON body
|
|
9
|
-
- **WebSocket**: `ws://HOST:3848/api/bus` send JSON message
|
|
10
|
-
- Both paths trigger bus auto-router for routable events
|
|
11
|
-
|
|
12
|
-
## Envelope Structure (All Events)
|
|
13
|
-
|
|
14
|
-
```json
|
|
15
|
-
{
|
|
16
|
-
"version": 1,
|
|
17
|
-
"message_id": "string (UUID or prefixed ID)",
|
|
18
|
-
"kind": "string (event type)",
|
|
19
|
-
"source": "string (sender identifier)",
|
|
20
|
-
"source_host": "string (machine_id of sender, e.g. hostname or Tailscale IP)",
|
|
21
|
-
"target": "string | null (target session ID, optional @host suffix)",
|
|
22
|
-
"ts": "ISO 8601 timestamp"
|
|
23
|
-
}
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
### Canonical Field Names
|
|
27
|
-
|
|
28
|
-
| Field | Type | Description |
|
|
29
|
-
|-------|------|-------------|
|
|
30
|
-
| `version` | number | Envelope schema version (currently 1) |
|
|
31
|
-
| `kind` | string | Event type (NOT `type` — `kind` is canonical) |
|
|
32
|
-
| `target` | string | Target telepty session ID. May include `@host` suffix for remote |
|
|
33
|
-
| `source` | string | Sender identifier (format: `project:session_id`) |
|
|
34
|
-
| `source_host` | string | Machine ID of sender (hostname or TELEPTY_MACHINE_ID) |
|
|
35
|
-
| `message_id` | string | Unique message identifier |
|
|
36
|
-
| `ts` | string | ISO 8601 timestamp |
|
|
37
|
-
|
|
38
|
-
## Cross-Machine Addressing
|
|
39
|
-
|
|
40
|
-
### Session Locator
|
|
41
|
-
Every session is uniquely identified by a locator triple:
|
|
42
|
-
```json
|
|
43
|
-
{ "machine_id": "hostname", "session_id": "aigentry-devkit-001", "project_id": "aigentry-devkit" }
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### Remote Target Format
|
|
47
|
-
`target` field supports `@host` suffix: `aigentry-devkit-001@100.100.100.5`
|
|
48
|
-
- Router strips suffix, resolves session on local daemon
|
|
49
|
-
- For cross-machine relay (P3), daemon forwards to target host
|
|
50
|
-
|
|
51
|
-
### Machine ID
|
|
52
|
-
- Default: `os.hostname()`
|
|
53
|
-
- Override: `TELEPTY_MACHINE_ID` env var
|
|
54
|
-
- Exposed in: `GET /api/meta` (`machine_id` field), session `locator` object, bus event `source_host`
|
|
55
|
-
|
|
56
|
-
### Global Session ID Uniqueness (P4)
|
|
57
|
-
- Convention: `{project}-{NNN}` (e.g. `aigentry-devkit-001`)
|
|
58
|
-
- Cross-machine uniqueness: guaranteed by `locator.machine_id` prefix in bus events
|
|
59
|
-
- Collision resolution: `resolveSessionAlias` returns local session only; remote sessions discovered via `source_host` field
|
|
60
|
-
- If two machines have `aigentry-devkit-001`, inject uses `target@host` to disambiguate
|
|
61
|
-
- Short form `aigentry-devkit-001` resolves to LOCAL session; remote requires explicit `@host`
|
|
62
|
-
|
|
63
|
-
### Peer Auth
|
|
64
|
-
- Localhost: always trusted
|
|
65
|
-
- Tailscale (100.x.y.z): trusted by default
|
|
66
|
-
- Custom peers: `TELEPTY_PEER_ALLOWLIST=ip1,ip2` env var
|
|
67
|
-
- All others: require `x-telepty-token` header
|
|
68
|
-
|
|
69
|
-
## Routable Events (Auto-Router)
|
|
70
|
-
|
|
71
|
-
### `turn_request`
|
|
72
|
-
|
|
73
|
-
Published by deliberation to request a turn from a session. Telepty daemon auto-routes to target session PTY.
|
|
74
|
-
|
|
75
|
-
```json
|
|
76
|
-
{
|
|
77
|
-
"message_id": "turn_request-<uuid>",
|
|
78
|
-
"session_id": "<deliberation_session_id>",
|
|
79
|
-
"project": "<project_name>",
|
|
80
|
-
"kind": "turn_request",
|
|
81
|
-
"source": "deliberation:<deliberation_session_id>",
|
|
82
|
-
"target": "<telepty_session_id>[@<host>]",
|
|
83
|
-
"reply_to": "<deliberation_session_id>",
|
|
84
|
-
"trace": ["project:<name>", "speaker:<id>", "turn:<turn_id>"],
|
|
85
|
-
"payload": {
|
|
86
|
-
"turn_id": "string",
|
|
87
|
-
"round": "number",
|
|
88
|
-
"max_rounds": "number",
|
|
89
|
-
"speaker": "string (target telepty session ID)",
|
|
90
|
-
"role": "string | null",
|
|
91
|
-
"prompt": "string (full prompt text — inject as-is to PTY)",
|
|
92
|
-
"prompt_sha1": "string (40-char SHA1)",
|
|
93
|
-
"history_entries": "number",
|
|
94
|
-
"transport_timeout_ms": "number",
|
|
95
|
-
"semantic_timeout_ms": "number"
|
|
96
|
-
},
|
|
97
|
-
"ts": "ISO 8601"
|
|
98
|
-
}
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
**Important Notes:**
|
|
102
|
-
- `session_id` is the DELIBERATION session ID, NOT the target telepty session
|
|
103
|
-
- `target` is the telepty session ID to inject into
|
|
104
|
-
- `payload.prompt` is the full text to write to PTY (no further processing needed)
|
|
105
|
-
- `@host` suffix on target: strip before resolving, use for remote routing
|
|
106
|
-
|
|
107
|
-
**Auto-Router Behavior:**
|
|
108
|
-
1. Daemon receives turn_request via HTTP POST or WS
|
|
109
|
-
2. Extracts `target` field, strips `@host` suffix
|
|
110
|
-
3. Resolves session via `resolveSessionAlias()`
|
|
111
|
-
4. Delivers `payload.prompt` to session PTY (kitty primary, WS fallback)
|
|
112
|
-
5. Emits `inject_written` ack on bus
|
|
113
|
-
|
|
114
|
-
### `inject_written` (ACK)
|
|
115
|
-
|
|
116
|
-
Emitted by telepty after successful auto-route delivery.
|
|
117
|
-
|
|
118
|
-
```json
|
|
119
|
-
{
|
|
120
|
-
"type": "inject_written",
|
|
121
|
-
"inject_id": "UUID",
|
|
122
|
-
"sender": "daemon",
|
|
123
|
-
"target_agent": "<session_id>",
|
|
124
|
-
"source_type": "bus_auto_route",
|
|
125
|
-
"delivered": true,
|
|
126
|
-
"timestamp": "ISO 8601"
|
|
127
|
-
}
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
## Session Lifecycle Events
|
|
131
|
-
|
|
132
|
-
### `session_register`
|
|
133
|
-
```json
|
|
134
|
-
{ "type": "session_register", "sender": "daemon", "session_id": "string", "command": "string", "cwd": "string", "timestamp": "ISO 8601" }
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
### `session.replaced`
|
|
138
|
-
```json
|
|
139
|
-
{ "type": "session.replaced", "sender": "daemon", "old_id": "string", "new_id": "string", "alias": "string", "timestamp": "ISO 8601" }
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### `session.idle`
|
|
143
|
-
```json
|
|
144
|
-
{ "type": "session.idle", "session_id": "string", "idleSeconds": "number", "lastActivityAt": "ISO 8601", "timestamp": "ISO 8601" }
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### `session_health` (periodic, every 10s)
|
|
148
|
-
```json
|
|
149
|
-
{ "type": "session_health", "session_id": "string", "payload": { "alive": true, "pid": "number|null", "type": "string", "clients": "number", "idleSeconds": "number|null" }, "timestamp": "ISO 8601" }
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
## Inject Events
|
|
153
|
-
|
|
154
|
-
### `inject_written`
|
|
155
|
-
```json
|
|
156
|
-
{ "type": "inject_written", "inject_id": "UUID", "sender": "daemon", "target_agent": "string", "content": "string", "from": "string|null", "reply_to": "string|null", "thread_id": "string|null", "reply_expected": "boolean", "timestamp": "ISO 8601" }
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
### `message_routed`
|
|
160
|
-
```json
|
|
161
|
-
{ "type": "message_routed", "message_id": "UUID", "from": "string", "to": "string", "reply_to": "string", "inject_id": "UUID", "deliberation_session_id": "string|null", "thread_id": "string|null", "timestamp": "ISO 8601" }
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
## Handoff Events
|
|
165
|
-
|
|
166
|
-
### `handoff.created` / `handoff.claimed` / `handoff.executing` / `handoff.completed`
|
|
167
|
-
```json
|
|
168
|
-
{ "type": "handoff.<status>", "handoff_id": "UUID", "source_session_id": "string|null", "deliberation_id": "string|null", "auto_execute": "boolean", "task_count": "number", "timestamp": "ISO 8601" }
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
## Thread Events
|
|
172
|
-
|
|
173
|
-
### `thread.opened`
|
|
174
|
-
```json
|
|
175
|
-
{ "type": "thread.opened", "thread_id": "UUID", "topic": "string", "orchestrator_session_id": "string|null", "participant_session_ids": ["string"], "timestamp": "ISO 8601" }
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
### `thread.closed`
|
|
179
|
-
```json
|
|
180
|
-
{ "type": "thread.closed", "thread_id": "UUID", "topic": "string", "message_count": "number", "timestamp": "ISO 8601" }
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
## Termination Signal Detection
|
|
184
|
-
|
|
185
|
-
Messages containing these strings suppress auto-reply guide footer:
|
|
186
|
-
- `no further reply needed`
|
|
187
|
-
- `thread closed` / `closed on X side`
|
|
188
|
-
- `ack received` / `ack-only`
|
|
189
|
-
- `회신 불필요` / `스레드 종료`
|
|
190
|
-
|
|
191
|
-
## Inject API Reference
|
|
192
|
-
|
|
193
|
-
### `POST /api/sessions/:id/inject`
|
|
194
|
-
|
|
195
|
-
```json
|
|
196
|
-
{
|
|
197
|
-
"prompt": "string (REQUIRED — canonical body field)",
|
|
198
|
-
"from": "string (sender session ID)",
|
|
199
|
-
"reply_to": "string (defaults to from if omitted)",
|
|
200
|
-
"thread_id": "string (optional)",
|
|
201
|
-
"reply_expected": "boolean (optional)",
|
|
202
|
-
"no_enter": "boolean (skip Enter after inject)"
|
|
203
|
-
}
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
**Note:** The canonical body field is `prompt`, NOT `text`, `content`, or `message`.
|
package/CLAUDE.md
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
# telepty — PTY Multiplexer & Session Orchestrator
|
|
2
|
-
|
|
3
|
-
aigentry 에코시스템의 **통신 인프라**. 멀티 AI 세션을 생성·연결·제어하는 PTY 멀티플렉서.
|
|
4
|
-
|
|
5
|
-
## 에코시스템 내 역할
|
|
6
|
-
|
|
7
|
-
9개 aigentry 세션(orchestrator, brain, amplify, dustcraw 등) 간 통신을 담당:
|
|
8
|
-
- 세션 생성/관리 (`allow`, `spawn`)
|
|
9
|
-
- 메시지 전달 (`inject`, `broadcast`, `multicast`, `reply`)
|
|
10
|
-
- 실시간 모니터링 (`tui`, `monitor`, `listen`)
|
|
11
|
-
- 세션 간 토론 조율 (`deliberate`)
|
|
12
|
-
|
|
13
|
-
## 아키텍처
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
CLI (cli.js) ──→ HTTP/WS ──→ Daemon (daemon.js:3848)
|
|
17
|
-
├── Session WS (/api/sessions/:id)
|
|
18
|
-
├── Event Bus WS (/api/bus)
|
|
19
|
-
└── REST API (/api/sessions/*)
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
### 핵심 모듈
|
|
23
|
-
|
|
24
|
-
| 파일 | 줄수 | 역할 |
|
|
25
|
-
|------|------|------|
|
|
26
|
-
| `cli.js` | ~1950 | CLI 명령 + allow-bridge (PTY 래핑) |
|
|
27
|
-
| `daemon.js` | ~1550 | HTTP/WS 서버, 세션 상태, inject 전달 |
|
|
28
|
-
| `tui.js` | ~500 | blessed 기반 TUI 대시보드 |
|
|
29
|
-
| `session-routing.js` | 81 | 세션 ID 해석, alias 매칭, 호스트 그룹핑 |
|
|
30
|
-
| `daemon-control.js` | 223 | 싱글톤 daemon PID 관리 |
|
|
31
|
-
| `auth.js` | 33 | UUID 토큰 기반 인증 |
|
|
32
|
-
| `interactive-terminal.js` | 71 | raw mode stdin/stdout 관리 |
|
|
33
|
-
| `skill-installer.js` | 269 | Claude/Codex/Gemini 스킬 설치 |
|
|
34
|
-
|
|
35
|
-
### Inject 전달 경로 (wrapped session)
|
|
36
|
-
|
|
37
|
-
1. **Primary**: `kitty @ send-text` (터미널 직접 전달, allow-bridge 우회)
|
|
38
|
-
2. **Fallback**: WS → allow-bridge → `child.write()` (PTY)
|
|
39
|
-
3. **Submit**: `osascript` Return 키 → kitty fallback → WS `\r`
|
|
40
|
-
|
|
41
|
-
busy 세션: CR은 큐에 대기 중인 텍스트와 함께 큐잉 후 올바른 순서로 flush.
|
|
42
|
-
|
|
43
|
-
## 명령어
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
# 테스트
|
|
47
|
-
npm test # 43 tests (node:test)
|
|
48
|
-
|
|
49
|
-
# 실행
|
|
50
|
-
telepty daemon # daemon 시작 (포트 3848)
|
|
51
|
-
telepty allow --id <name> claude # 세션 래핑
|
|
52
|
-
telepty tui # TUI 대시보드
|
|
53
|
-
telepty list # 세션 목록
|
|
54
|
-
telepty inject <id> "msg" # 메시지 주입
|
|
55
|
-
telepty broadcast "msg" # 전체 브로드캐스트
|
|
56
|
-
telepty session start --launch # kitty 탭으로 다중 세션 시작
|
|
57
|
-
|
|
58
|
-
# 릴리스
|
|
59
|
-
npm version patch --no-git-tag-version && npm publish --access public
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
## 주요 규칙
|
|
63
|
-
|
|
64
|
-
- inject 후 submit은 항상 `osascript`로 통일 (`--no-enter` + osascript keystroke)
|
|
65
|
-
- inject 시 발신자 session ID (`--from`)를 항상 포함
|
|
66
|
-
- PTY `\r` 직접 의존 금지
|
|
67
|
-
|
|
68
|
-
## 최근 주요 변경 (v0.1.58–0.3.3)
|
|
69
|
-
|
|
70
|
-
| 버전 | 변경 |
|
|
71
|
-
|------|------|
|
|
72
|
-
| 0.3.3 | inject `--submit-force` (gate bypass) + idempotent `--submit-retry` (default 1, retry-safe 504만). 클라이언트 측 변경, daemon 무수정. task #347. |
|
|
73
|
-
| 0.3.2 | Layer 3 prompt-symbol 렌더 게이트 — claude/codex/gemini 별 prompt symbol을 cmux read-screen으로 polling. |
|
|
74
|
-
| 0.3.1 | 게이트 임계값 0.85 → 0.5 완화 + dispatch-on-timeout best-effort + send-key force=true 우회 추가. |
|
|
75
|
-
| 0.3.0 | Render-gated submit (sessionStateManager 기반). Enter 송신 전 REPL ready 검증. |
|
|
76
|
-
| 0.1.62 | TUI 태스크 추적 — bus 이벤트에서 [태그] 자동 파싱, 세션별 상태 표시 |
|
|
77
|
-
| 0.1.61 | reconnect 시 resize/\x0c 제거 (멀티터미널 깜빡임 수정) |
|
|
78
|
-
| 0.1.60 | TUI P1 — s=start, k=kill, p=purge stale |
|
|
79
|
-
| 0.1.59 | wrapped inject 503 반환 + 테스트 43/43 정합성 |
|
|
80
|
-
| 0.1.58 | inject busy-session CR/text 순서 수정 + kittyWindowId 캐시 무효화 |
|
|
81
|
-
|
|
82
|
-
## 자율 재귀적 오케스트레이션
|
|
83
|
-
|
|
84
|
-
이 세션은 작업 복잡도가 높거나, 독립 도메인이 식별되거나, 컨텍스트 분리가 필요하다고 판단되면 — 사용자 지시 없이 자율적으로:
|
|
85
|
-
|
|
86
|
-
1. 자기 프로젝트 하위에 폴더를 생성한다
|
|
87
|
-
2. 해당 폴더에 CLAUDE.md를 작성한다 (역할, 범위, 상위 세션과의 통신 방법)
|
|
88
|
-
3. aigentry scaffold 또는 telepty allow로 하위 Claude 세션을 생성한다
|
|
89
|
-
4. telepty inject로 하위 세션에 태스크를 주입한다
|
|
90
|
-
5. 하위 세션의 결과를 수신하고 통합한다
|
|
91
|
-
|
|
92
|
-
판단 기준:
|
|
93
|
-
- 현재 작업이 2개 이상 독립 도메인을 포함할 때
|
|
94
|
-
- 컨텍스트 윈도우의 30% 이상을 단일 하위 작업이 차지할 때
|
|
95
|
-
- 반복적 전문 작업이 식별될 때 (SEO, 특정 채널, 특정 데이터 소스 등)
|
|
96
|
-
|
|
97
|
-
원칙:
|
|
98
|
-
- YAGNI: 진짜 필요할 때만 생성. 과잉 분리 금지.
|
|
99
|
-
- 하위 세션 완료 시 오케스트레이터(상위)에게 반드시 보고.
|
|
100
|
-
- 하위 세션의 결과물은 상위 프로젝트에 통합(커밋).
|
package/GEMINI.md
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
@AGENTS.md
|
|
2
|
-
|
|
3
|
-
# Gemini CLI — aigentry-telepty
|
|
4
|
-
|
|
5
|
-
## Gemini 전용 설정
|
|
6
|
-
|
|
7
|
-
- 세션 ID: `aigentry-telepty-gemini`
|
|
8
|
-
- 보고: `telepty inject --ref --from aigentry-telepty-gemini aigentry-orchestrator-claude "보고 내용"`
|
|
9
|
-
- Gemini 강점 활용: upstream 이슈 검색, API 리서치, 문서화 우선
|
|
10
|
-
- 헌법: `~/projects/aigentry/docs/CONSTITUTION.md`
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
RESOLVED - all 3 urgent issues fixed in 40b8e47
|