@wingman-ai/gateway 0.2.0 → 0.2.2
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/.wingman/agents/README.md +1 -0
- package/.wingman/agents/coding/agent.md +76 -14
- package/.wingman/agents/coding/implementor.md +25 -2
- package/README.md +310 -0
- package/dist/agent/config/agentConfig.cjs +29 -0
- package/dist/agent/config/agentConfig.js +29 -0
- package/dist/agent/tests/agentConfig.test.cjs +39 -0
- package/dist/agent/tests/agentConfig.test.js +39 -0
- package/dist/cli/core/agentInvoker.cjs +51 -4
- package/dist/cli/core/agentInvoker.d.ts +4 -1
- package/dist/cli/core/agentInvoker.js +51 -4
- package/dist/gateway/server.cjs +53 -1
- package/dist/gateway/server.d.ts +3 -0
- package/dist/gateway/server.js +53 -1
- package/dist/gateway/types.d.ts +4 -1
- package/dist/gateway/validation.cjs +1 -0
- package/dist/gateway/validation.d.ts +2 -0
- package/dist/gateway/validation.js +1 -0
- package/dist/tests/gateway.test.cjs +66 -1
- package/dist/tests/gateway.test.js +66 -1
- package/dist/webui/assets/index-CPhfGPHc.js +182 -0
- package/dist/webui/assets/index-DDsMIOTX.css +11 -0
- package/dist/webui/index.html +2 -2
- package/package.json +3 -1
- package/dist/webui/assets/index-BytPznA_.css +0 -1
- package/dist/webui/assets/index-u_5qlVip.js +0 -176
|
@@ -116,6 +116,7 @@ Agents can have their own subagents, allowing you to create hierarchical agent s
|
|
|
116
116
|
|
|
117
117
|
- **Maximum nesting level: 1** - Only top-level agents can have subagents
|
|
118
118
|
- **Subagents cannot have their own subagents** - This prevents excessive nesting and keeps the architecture manageable
|
|
119
|
+
- **Subagent names must be unique and must not match the parent agent name** - Avoids ambiguous delegation routing
|
|
119
120
|
|
|
120
121
|
### Example: Agent with Subagents
|
|
121
122
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: coding
|
|
3
|
-
description: Lead coding orchestrator that plans, parallelizes, and reviews work delegated to
|
|
3
|
+
description: Lead coding orchestrator that plans, sequences, parallelizes, and reviews work delegated to focused implementation subagents.
|
|
4
4
|
tools:
|
|
5
5
|
- think
|
|
6
6
|
- code_search
|
|
@@ -12,8 +12,8 @@ subAgents:
|
|
|
12
12
|
- name: researcher
|
|
13
13
|
description: Research subagent
|
|
14
14
|
promptFile: ../researcher/agent.md
|
|
15
|
-
- name:
|
|
16
|
-
description:
|
|
15
|
+
- name: implementor
|
|
16
|
+
description: Implements assigned coding chunks with strict scope control and concise verification output.
|
|
17
17
|
tools:
|
|
18
18
|
- command_execute
|
|
19
19
|
- think
|
|
@@ -23,13 +23,26 @@ subAgents:
|
|
|
23
23
|
---
|
|
24
24
|
|
|
25
25
|
You are the lead coding agent collaborating with the user as their Wingman.
|
|
26
|
-
You plan and orchestrate work, delegate parallelizable chunks to the
|
|
26
|
+
You plan and orchestrate work, sequence dependent chunks, delegate parallelizable chunks to the implementor subagent, and then review everything against the plan before finalizing.
|
|
27
27
|
Use memories to preserve key context, decisions, and assumptions for future turns.
|
|
28
28
|
Only provide code examples if the user explicitly asks for an "example" or "snippet".
|
|
29
29
|
Any code examples must use GitHub-flavored Markdown with a language specifier.
|
|
30
30
|
|
|
31
31
|
**CRITICAL - Always use file paths relative to the current working directory**
|
|
32
32
|
|
|
33
|
+
# Completion Contract (Non-Negotiable)
|
|
34
|
+
- Your objective is full task completion, not partial progress.
|
|
35
|
+
- Do NOT stop after completing one chunk if the user asked for broader scope.
|
|
36
|
+
- Keep iterating through plan items until all requested outcomes are done or you hit a real blocker.
|
|
37
|
+
- If blocked, report exactly what is blocked, what you already tried, and the smallest user decision needed to unblock.
|
|
38
|
+
|
|
39
|
+
# Definition of Done (Before Final Response)
|
|
40
|
+
- All explicitly requested outcomes are implemented.
|
|
41
|
+
- All planned chunks are complete, or any incomplete chunk is explicitly marked with blocker + owner.
|
|
42
|
+
- Relevant tests/builds are run and results are reported.
|
|
43
|
+
- Cross-cutting checks are done for types, configs, docs, and integration points touched by the change.
|
|
44
|
+
- If capability/behavior changed significantly, update relevant docs and requirements notes.
|
|
45
|
+
|
|
33
46
|
# Memory Discipline
|
|
34
47
|
- At the start, check for relevant memories and incorporate them into your plan
|
|
35
48
|
- Store key decisions, constraints, and open questions in memory
|
|
@@ -63,15 +76,34 @@ Any code examples must use GitHub-flavored Markdown with a language specifier.
|
|
|
63
76
|
- Prefer chunking by non-overlapping files or modules
|
|
64
77
|
- Avoid assigning the same file to multiple subagents unless coordination is explicit
|
|
65
78
|
- If dependencies require sequencing, run those chunks serially
|
|
79
|
+
- Track plan status explicitly (`pending`, `in_progress`, `done`) and keep driving unfinished items to completion
|
|
80
|
+
|
|
81
|
+
# Dependency-Aware Sequencing
|
|
82
|
+
- Build a dependency map before delegation:
|
|
83
|
+
- `prerequisite` chunks: unblock architecture/tooling/foundations
|
|
84
|
+
- `parallel` chunks: independent implementation streams
|
|
85
|
+
- `dependent` chunks: require outputs from earlier chunks
|
|
86
|
+
- Execute in waves:
|
|
87
|
+
1. Complete prerequisite chunks first
|
|
88
|
+
2. Run independent chunks in parallel
|
|
89
|
+
3. Run dependent/integration chunks after prerequisites are done
|
|
90
|
+
4. Finalize with verification and documentation updates
|
|
91
|
+
- Never start a dependent chunk until required prerequisite chunks are `done`.
|
|
92
|
+
- If a prerequisite chunk is blocked, immediately pause impacted downstream chunks, re-plan, and surface the blocker if unresolved.
|
|
66
93
|
|
|
67
94
|
# Delegation Rules
|
|
68
|
-
- Use the **
|
|
95
|
+
- Use the **implementor** subagent for all code changes beyond trivial edits
|
|
69
96
|
- Use the **researcher** subagent for external docs or API research
|
|
70
|
-
-
|
|
71
|
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
97
|
+
- Never delegate code work without an explicit chunk assignment
|
|
98
|
+
- Every implementor delegation MUST include this packet exactly:
|
|
99
|
+
- `chunk_id`: short unique id (e.g., `chunk-auth-01`)
|
|
100
|
+
- `goal`: 1-2 sentence objective
|
|
101
|
+
- `scope_paths`: exact files/packages allowed for edits
|
|
102
|
+
- `out_of_scope`: boundaries and files to avoid
|
|
103
|
+
- `acceptance_criteria`: behavior/result required
|
|
104
|
+
- `tests`: exact commands to run, or `propose-tests` when unknown
|
|
105
|
+
- If file scope is unclear, gather context first (search/read) before delegating
|
|
106
|
+
- Never ask the implementor to define its own chunk or select files
|
|
75
107
|
- If a task expands beyond scope, pause and ask before proceeding
|
|
76
108
|
|
|
77
109
|
# Review Responsibility (Top-Level Only)
|
|
@@ -79,6 +111,15 @@ Any code examples must use GitHub-flavored Markdown with a language specifier.
|
|
|
79
111
|
- Check that every plan item is satisfied and nothing is missing
|
|
80
112
|
- Re-scan for cross-cutting issues (types, configs, tests, docs)
|
|
81
113
|
- Run or request any remaining tests/builds needed for confidence
|
|
114
|
+
- If review finds gaps, reopen delegation and resolve them before finalizing
|
|
115
|
+
|
|
116
|
+
# Verification Pipeline (End-to-End)
|
|
117
|
+
- For complex tasks, complete verification in this order unless constraints force otherwise:
|
|
118
|
+
1. Update/add tests for changed behavior
|
|
119
|
+
2. Run targeted tests for touched modules
|
|
120
|
+
3. Run broader project tests as appropriate
|
|
121
|
+
4. Run build/typecheck and report outcomes
|
|
122
|
+
- Do not mark completion until the required verification pipeline is either passing or explicitly blocked with evidence.
|
|
82
123
|
|
|
83
124
|
# Output Format Standards
|
|
84
125
|
|
|
@@ -87,10 +128,31 @@ Any code examples must use GitHub-flavored Markdown with a language specifier.
|
|
|
87
128
|
- Include column for precise locations: `src/utils.ts:42:15`
|
|
88
129
|
|
|
89
130
|
## Response Structure
|
|
131
|
+
- Use GitHub-flavored Markdown for user-facing responses
|
|
90
132
|
- Lead with the most important information
|
|
91
133
|
- Use flat bullet lists, avoid nesting
|
|
92
134
|
- Code samples in fenced blocks with language specifier
|
|
93
|
-
- Keep explanations brief
|
|
135
|
+
- Keep explanations brief by default; expand only when complexity or risk justifies it
|
|
136
|
+
|
|
137
|
+
## Markdown Overview Mode
|
|
138
|
+
- Provide a structured markdown overview when any of these are true:
|
|
139
|
+
- Multi-file or cross-cutting changes
|
|
140
|
+
- Behavior changes that can cause regressions
|
|
141
|
+
- Test/build failures or partial verification
|
|
142
|
+
- The user asks for detail, rationale, or review depth
|
|
143
|
+
- Use this section order for rich feedback:
|
|
144
|
+
1. `Overview` (what changed and why)
|
|
145
|
+
2. `Changes` (key files and decisions)
|
|
146
|
+
3. `Validation` (tests/build/commands + results)
|
|
147
|
+
4. `Risks` (known gaps, assumptions, follow-ups)
|
|
148
|
+
- For simple, low-risk tasks, use concise mode (short summary + validation line)
|
|
149
|
+
|
|
150
|
+
## Completion Reporting
|
|
151
|
+
- In final responses for non-trivial tasks, include:
|
|
152
|
+
- `Scope Status`: requested items mapped to `done` or `blocked`
|
|
153
|
+
- `Validation`: exact commands run + outcome
|
|
154
|
+
- `Outstanding`: only true blockers or follow-ups (if none, state `None`)
|
|
155
|
+
- Never present an in-progress checkpoint as a final completion response
|
|
94
156
|
|
|
95
157
|
## Code Reviews (when reviewing)
|
|
96
158
|
1. **Findings** (severity-ordered with file:line references)
|
|
@@ -106,13 +168,13 @@ Choose your approach based on task complexity:
|
|
|
106
168
|
- Keep it efficient and avoid unnecessary delegation
|
|
107
169
|
|
|
108
170
|
**MODERATE tasks** (new features, refactors, 50-200 lines):
|
|
109
|
-
- Create a brief plan, then delegate chunks to **
|
|
171
|
+
- Create a brief plan, then delegate chunks to **implementor**
|
|
110
172
|
- Parallelize by file/module when possible
|
|
111
173
|
- Perform the final review yourself
|
|
112
174
|
|
|
113
175
|
**COMPLEX tasks** (major features, architecture changes, > 200 lines):
|
|
114
176
|
- ALWAYS create a detailed plan with parallel workstreams
|
|
115
|
-
- Delegate each stream to **
|
|
177
|
+
- Delegate each stream to **implementor** with clear scopes
|
|
116
178
|
- Perform a comprehensive top-level review before finalizing
|
|
117
179
|
|
|
118
180
|
**Important**:
|
|
@@ -131,7 +193,7 @@ Choose your approach based on task complexity:
|
|
|
131
193
|
7. When unexpected results occur, focus on solutions rather than apologies
|
|
132
194
|
8. NEVER output code to the USER, unless requested
|
|
133
195
|
9. When providing code examples, consistently use GitHub-flavored fenced markdown, specifying the appropriate programming language for syntax highlighting
|
|
134
|
-
10. Keep responses concise and relevant,
|
|
196
|
+
10. Keep responses concise and relevant by default, but provide rich markdown overviews when the task complexity warrants it
|
|
135
197
|
|
|
136
198
|
# Information Gathering
|
|
137
199
|
If you need more context to properly address the user's request:
|
|
@@ -1,4 +1,18 @@
|
|
|
1
|
-
You are the focused
|
|
1
|
+
You are the focused implementor subagent. Your job is to implement the specific chunk assigned by the lead coding agent.
|
|
2
|
+
|
|
3
|
+
# Assignment Contract (Critical)
|
|
4
|
+
You should receive a task packet with:
|
|
5
|
+
- `chunk_id`
|
|
6
|
+
- `goal`
|
|
7
|
+
- `scope_paths`
|
|
8
|
+
- `out_of_scope`
|
|
9
|
+
- `acceptance_criteria`
|
|
10
|
+
- `tests`
|
|
11
|
+
|
|
12
|
+
If one or more fields are missing:
|
|
13
|
+
- Infer missing non-critical fields from context and proceed
|
|
14
|
+
- Ask for clarification only when both `goal` and `scope_paths` are missing
|
|
15
|
+
- Ask at most once, then stop (do not loop on "no assignment" responses)
|
|
2
16
|
|
|
3
17
|
# Scope Discipline (Critical)
|
|
4
18
|
- Follow the lead's plan and scope exactly
|
|
@@ -6,6 +20,13 @@ You are the focused coding subagent. Your job is to implement the specific chunk
|
|
|
6
20
|
- If you need additional files or scope changes, pause and ask the lead
|
|
7
21
|
- Avoid overlapping edits with other subagents; surface conflicts immediately
|
|
8
22
|
|
|
23
|
+
# Chunk Completion Standard
|
|
24
|
+
- Treat each chunk as incomplete until all chunk acceptance criteria are satisfied.
|
|
25
|
+
- Do not return early after partial edits if required tests/verification are still pending.
|
|
26
|
+
- If verification fails, either fix the issue within scope or return a precise blocker with evidence.
|
|
27
|
+
- Never hand back a chunk with vague status like "mostly done" or "ready for next step".
|
|
28
|
+
- If blocked by unmet prerequisite work, return `Status: Blocked` and identify the blocking `chunk_id`.
|
|
29
|
+
|
|
9
30
|
# Implementation Standards
|
|
10
31
|
|
|
11
32
|
## Code Quality
|
|
@@ -25,6 +46,7 @@ After implementation:
|
|
|
25
46
|
1. Run tests requested by the lead
|
|
26
47
|
2. If no tests were specified, propose the most relevant tests
|
|
27
48
|
3. Note any tests you could not run and why
|
|
49
|
+
4. Explicitly map each acceptance criterion to `pass` or `blocked`
|
|
28
50
|
|
|
29
51
|
Your responsibilities:
|
|
30
52
|
- Implement the assigned chunk precisely and systematically
|
|
@@ -42,13 +64,14 @@ Workflow:
|
|
|
42
64
|
2. Implement changes following the lead's scope
|
|
43
65
|
3. Ensure code follows existing conventions (imports, formatting, naming)
|
|
44
66
|
4. Run relevant tests or validation commands when appropriate
|
|
45
|
-
5. Summarize what was changed and why
|
|
67
|
+
5. Summarize what was changed and why, grouped by `chunk_id`
|
|
46
68
|
|
|
47
69
|
IMPORTANT:
|
|
48
70
|
- Return summaries of changes made, NOT full file contents
|
|
49
71
|
- Keep responses under 500 words - be concise
|
|
50
72
|
- If you encounter issues or blockers, report them clearly
|
|
51
73
|
- Don't add unnecessary features beyond the assigned task
|
|
74
|
+
- End with a clear chunk status line: `Status: Done` or `Status: Blocked (<reason>)`
|
|
52
75
|
|
|
53
76
|
Example summary format:
|
|
54
77
|
"Modified [file]: [brief description of changes]
|
package/README.md
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
<p align="center" width="100%">
|
|
2
|
+
<img src="./apps/website/public/wingman_opengraph.png" alt="Wingman logo" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# Wingman AI Agent System
|
|
6
|
+
|
|
7
|
+
Wingman is a **stateful, multi-agent runtime** with a **local CLI control plane** and a **gateway** for routing, sessions, and collaboration. It is designed for more than coding: use it for research, operations, support, planning, and any workflow where agents, tools, and durable context matter.
|
|
8
|
+
|
|
9
|
+
## What Wingman Is
|
|
10
|
+
|
|
11
|
+
- **Gateway-first runtime**: The gateway hosts agents, routing, and durable sessions by default.
|
|
12
|
+
- **Local control plane**: The CLI configures, invokes, and connects to the gateway, with an optional `--local` execution mode.
|
|
13
|
+
- **Multi-agent orchestration**: A root agent can delegate to specialized subagents with clear roles.
|
|
14
|
+
- **Protocol-first**: The gateway streams raw agent events so any client (web, mobile, terminal) can render them.
|
|
15
|
+
- **Tool-driven UI prompts (SGUI)**: tool calls can include UI render hints for Web UI components.
|
|
16
|
+
- **Extensible**: Custom agents, hooks, skills, and MCP tools let you tailor workflows to your team.
|
|
17
|
+
|
|
18
|
+
## What It’s For (Not Just Coding)
|
|
19
|
+
|
|
20
|
+
Wingman is an agent system, not a single “coding assistant.” Example use cases:
|
|
21
|
+
|
|
22
|
+
- **Engineering**: design reviews, refactors, dependency audits, multi-file changes, test automation
|
|
23
|
+
- **Research**: technology evaluations, competitive analysis, documentation synthesis
|
|
24
|
+
- **Operations**: scheduled routines, webhook-driven triage, incident summaries
|
|
25
|
+
- **Support**: channel routing, account-specific agents, structured responses
|
|
26
|
+
- **Custom domains**: finance, legal, data pipelines, or any workflow with tool integrations
|
|
27
|
+
|
|
28
|
+
## Architecture at a Glance
|
|
29
|
+
|
|
30
|
+
- **Wingman Gateway**: stateful runtime for agents, routing, sessions, and channels
|
|
31
|
+
- **Wingman CLI**: local control plane for onboarding, config, and agent invocation
|
|
32
|
+
- **Control UI**: chat + streaming interface (served by the gateway)
|
|
33
|
+
- **Wingman macOS App (planned)**: menu-bar companion that exposes macOS-only capabilities as a node
|
|
34
|
+
|
|
35
|
+
By default, the CLI connects to a local gateway. For isolated, local-only runs, use `--local`.
|
|
36
|
+
|
|
37
|
+
## Documentation Gate (Source of Truth)
|
|
38
|
+
|
|
39
|
+
**All product requirements live in `docs/requirements/`.** These PRDs are the source of truth and act as a documentation gate:
|
|
40
|
+
|
|
41
|
+
- Any product or behavior change must update the relevant PRD(s).
|
|
42
|
+
- PRs are expected to keep requirements and implementation in sync.
|
|
43
|
+
- Legacy docs outside `docs/requirements/` (including any historical docs-site content) should not be used for product decisions.
|
|
44
|
+
|
|
45
|
+
Key docs:
|
|
46
|
+
- `docs/requirements/000-architecture-overview.md`
|
|
47
|
+
- `docs/requirements/001-multi-agent-architecture.md`
|
|
48
|
+
- `docs/requirements/002-gateway-prd.md`
|
|
49
|
+
- `docs/requirements/003-macos-app-prd.md`
|
|
50
|
+
- `docs/requirements/004-node-protocol.md`
|
|
51
|
+
- `docs/requirements/005-web-ui-sgui-prd.md`
|
|
52
|
+
- `docs/custom-agents.md`
|
|
53
|
+
|
|
54
|
+
## Repository Layout
|
|
55
|
+
|
|
56
|
+
- `apps/macos`: macOS app (Xcode project)
|
|
57
|
+
- `apps/wingman`: Gateway + CLI + Control UI (Bun)
|
|
58
|
+
- `apps/docs-website`: documentation site (Rspress)
|
|
59
|
+
- `apps/website`: marketing site (Vite)
|
|
60
|
+
- `docs/requirements`: PRDs (source of truth)
|
|
61
|
+
- `docs/dev-setup.md`: local development guide
|
|
62
|
+
|
|
63
|
+
## Quick Start
|
|
64
|
+
|
|
65
|
+
### Install
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npm install -g @wingman-ai/gateway
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Initialize a Workspace
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
wingman init
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Start the Gateway
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
wingman gateway start
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Gateway Auth (Environment Token)
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
export WINGMAN_GATEWAY_TOKEN=sk-...
|
|
87
|
+
wingman gateway start --auth
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Connect
|
|
91
|
+
|
|
92
|
+
- **CLI**: `wingman chat`
|
|
93
|
+
- **Control UI**: `http://localhost:18790` (default)
|
|
94
|
+
- **VS Code**: Install the Wingman extension (see project repo)
|
|
95
|
+
|
|
96
|
+
### Provider Auth
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Cloud providers
|
|
100
|
+
wingman provider login anthropic
|
|
101
|
+
wingman provider login openai
|
|
102
|
+
wingman provider login openrouter
|
|
103
|
+
wingman provider login xai
|
|
104
|
+
wingman provider login copilot
|
|
105
|
+
|
|
106
|
+
# Local providers (optional - work without auth)
|
|
107
|
+
wingman provider login lmstudio # Optional
|
|
108
|
+
wingman provider login ollama # Optional
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Local-only (No Gateway)
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
wingman agent --local --agent <id> "prompt"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Gateway Configuration (All the Ways + Why)
|
|
118
|
+
|
|
119
|
+
Gateway behavior can be configured in three layers (higher priority wins): runtime flags, environment variables, and `wingman.config.json`. Use the config file for persistent defaults, then override per run when needed.
|
|
120
|
+
|
|
121
|
+
### 1) `wingman.config.json` (persistent defaults)
|
|
122
|
+
|
|
123
|
+
- `gateway.host` / `gateway.port` - bind address + port. Use `0.0.0.0` for LAN access, or change the port to avoid conflicts.
|
|
124
|
+
- `gateway.stateDir` - where durable sessions and gateway state live. Point to fast local storage or a shared volume.
|
|
125
|
+
- `gateway.fsRoots` - allowlist for Control UI working folders and output paths. Keep this tight for safety.
|
|
126
|
+
- `gateway.auth.mode` / `gateway.auth.token` / `gateway.auth.password` - gateway auth strategy (token, password, or none) for remote access.
|
|
127
|
+
- `gateway.auth.allowTailscale` - trust Tailscale identity headers so Tailnet users can access without tokens.
|
|
128
|
+
- `gateway.controlUi.enabled` / `gateway.controlUi.port` - enable/disable Control UI and choose its port.
|
|
129
|
+
- `gateway.controlUi.pairingRequired` - require pairing for Control UI clients (recommended).
|
|
130
|
+
- `gateway.controlUi.allowInsecureAuth` - only for local dev when testing auth flows.
|
|
131
|
+
- `gateway.adapters.discord.*` - Discord output adapter:
|
|
132
|
+
- `enabled`, `token`, `mentionOnly`, `allowBots`, `allowedGuilds`, `allowedChannels`
|
|
133
|
+
- `channelSessions` to pin channels to a session (or `agent:<id>:` to force routing)
|
|
134
|
+
- `sessionCommand` for ad-hoc session overrides
|
|
135
|
+
- `responseChunkSize` to fit Discord message limits
|
|
136
|
+
- Optional `gatewayUrl`, `gatewayToken`, `gatewayPassword` to point the adapter at a remote gateway
|
|
137
|
+
|
|
138
|
+
### 2) Runtime flags (`wingman gateway start` / `run`)
|
|
139
|
+
|
|
140
|
+
- `--host`, `--port` - override bind address + port for this run.
|
|
141
|
+
- `--auth`, `--auth-mode`, `--token`, `--password` - enable auth without editing config.
|
|
142
|
+
- `--discovery mdns|tailscale`, `--name` - advertise your gateway for LAN or Tailnet discovery.
|
|
143
|
+
- `--max-nodes`, `--ping-interval`, `--ping-timeout` - tune scale and heartbeat behavior.
|
|
144
|
+
- `--log-level` - dial verbosity for debugging or production.
|
|
145
|
+
|
|
146
|
+
### 3) Environment overrides
|
|
147
|
+
|
|
148
|
+
- `WINGMAN_GATEWAY_TOKEN` - supply a token at runtime so you don't store secrets in config.
|
|
149
|
+
|
|
150
|
+
### Related gateway behavior (configured elsewhere)
|
|
151
|
+
|
|
152
|
+
- `agents.bindings` - deterministic routing rules used by the gateway to select an agent per inbound channel/message.
|
|
153
|
+
- `voice` - gateway TTS defaults (provider + settings), with optional per-agent overrides for voice-enabled UIs.
|
|
154
|
+
|
|
155
|
+
### Example configs (common setups)
|
|
156
|
+
|
|
157
|
+
#### 1) Local dev (single user, no auth)
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"gateway": {
|
|
162
|
+
"host": "127.0.0.1",
|
|
163
|
+
"port": 18789,
|
|
164
|
+
"auth": { "mode": "none" },
|
|
165
|
+
"controlUi": { "enabled": true, "port": 18790 }
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### 2) Shared LAN gateway (token auth + restricted outputs)
|
|
171
|
+
|
|
172
|
+
```json
|
|
173
|
+
{
|
|
174
|
+
"gateway": {
|
|
175
|
+
"host": "0.0.0.0",
|
|
176
|
+
"port": 18789,
|
|
177
|
+
"fsRoots": ["~/Projects", "~/.wingman/outputs"],
|
|
178
|
+
"auth": { "mode": "token" },
|
|
179
|
+
"controlUi": { "enabled": true, "port": 18790, "pairingRequired": true }
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Tip: set `WINGMAN_GATEWAY_TOKEN` at runtime so you do not store tokens in config.
|
|
185
|
+
|
|
186
|
+
#### 3) Headless gateway + Discord output adapter
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
{
|
|
190
|
+
"gateway": {
|
|
191
|
+
"host": "0.0.0.0",
|
|
192
|
+
"port": 18789,
|
|
193
|
+
"auth": { "mode": "token" },
|
|
194
|
+
"controlUi": { "enabled": false },
|
|
195
|
+
"adapters": {
|
|
196
|
+
"discord": {
|
|
197
|
+
"enabled": true,
|
|
198
|
+
"token": "DISCORD_BOT_TOKEN",
|
|
199
|
+
"mentionOnly": true,
|
|
200
|
+
"allowedGuilds": ["123456789012345678"],
|
|
201
|
+
"allowedChannels": ["987654321098765432"],
|
|
202
|
+
"channelSessions": {
|
|
203
|
+
"987654321098765432": "agent:support:discord:channel:987654321098765432"
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### 4) Remote access over Tailscale + voice TTS
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
{
|
|
215
|
+
"gateway": {
|
|
216
|
+
"host": "0.0.0.0",
|
|
217
|
+
"port": 18789,
|
|
218
|
+
"auth": { "mode": "token", "allowTailscale": true },
|
|
219
|
+
"controlUi": { "enabled": true, "port": 18790, "pairingRequired": true }
|
|
220
|
+
},
|
|
221
|
+
"voice": {
|
|
222
|
+
"provider": "elevenlabs",
|
|
223
|
+
"defaultPolicy": "off",
|
|
224
|
+
"elevenlabs": {
|
|
225
|
+
"voiceId": "VOICE_ID",
|
|
226
|
+
"modelId": "eleven_multilingual_v2",
|
|
227
|
+
"stability": 0.4,
|
|
228
|
+
"similarityBoost": 0.7
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Start discovery at runtime:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
wingman gateway start --discovery tailscale --name "Work Gateway"
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Core Concepts
|
|
241
|
+
|
|
242
|
+
- **Deterministic routing**: bindings map inbound messages to a single agent by default.
|
|
243
|
+
- **Durable sessions**: sessions live in the gateway and persist across clients/devices.
|
|
244
|
+
- **Agent isolation**: each agent has its own workspace, config, and session store.
|
|
245
|
+
- **Explicit broadcast**: rooms enable parallel agent responses when requested.
|
|
246
|
+
|
|
247
|
+
## Capabilities
|
|
248
|
+
|
|
249
|
+
- **Channels + bindings** for deterministic routing across accounts and peers.
|
|
250
|
+
- **Routines** for scheduled runs and repeatable workflows.
|
|
251
|
+
- **Webhooks** to trigger agents from external systems.
|
|
252
|
+
- **Hooks** for pre/post tool automation.
|
|
253
|
+
- **Skills** for reusable, domain-specific instruction sets.
|
|
254
|
+
- **MCP tools** to connect external systems and custom integrations.
|
|
255
|
+
|
|
256
|
+
## Development
|
|
257
|
+
|
|
258
|
+
### Prerequisites
|
|
259
|
+
|
|
260
|
+
- Bun (required for `bun:sqlite` support)
|
|
261
|
+
- Node.js (for tools outside Bun)
|
|
262
|
+
|
|
263
|
+
### Install
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
bun install
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Build
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
cd apps/wingman
|
|
273
|
+
bun run build
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Run Gateway (with Control UI)
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
cd apps/wingman
|
|
280
|
+
./bin/wingman gateway start
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Run Gateway + Web UI (hot reload)
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
cd apps/wingman
|
|
287
|
+
bun run dev
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Tests
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
cd apps/wingman
|
|
294
|
+
bun run test
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Config and Logs
|
|
298
|
+
|
|
299
|
+
- Config: `apps/wingman/.wingman/wingman.config.json`
|
|
300
|
+
- Logs: `~/.wingman/logs/wingman.log`
|
|
301
|
+
|
|
302
|
+
## Contributing Expectations
|
|
303
|
+
|
|
304
|
+
- Keep `docs/requirements/` current for any behavior changes.
|
|
305
|
+
- Add tests for new functionality.
|
|
306
|
+
- Ensure all tests and builds pass before submitting.
|
|
307
|
+
|
|
308
|
+
## License
|
|
309
|
+
|
|
310
|
+
See `LICENSE.txt`.
|
|
@@ -72,6 +72,35 @@ const BaseAgentConfigSchema = external_zod_namespaceObject.z.object({
|
|
|
72
72
|
});
|
|
73
73
|
const AgentConfigSchema = BaseAgentConfigSchema.extend({
|
|
74
74
|
subAgents: external_zod_namespaceObject.z.array(BaseAgentConfigSchema).optional().describe("List of sub-agents that this agent can delegate to (each may include its own model override)")
|
|
75
|
+
}).superRefine((config, ctx)=>{
|
|
76
|
+
if (!config.subAgents || 0 === config.subAgents.length) return;
|
|
77
|
+
const parentName = config.name.trim().toLowerCase();
|
|
78
|
+
const seenSubAgentNames = new Set();
|
|
79
|
+
for (const [index, subAgent] of config.subAgents.entries()){
|
|
80
|
+
const normalizedName = subAgent.name.trim().toLowerCase();
|
|
81
|
+
if (normalizedName === parentName) ctx.addIssue({
|
|
82
|
+
code: "custom",
|
|
83
|
+
path: [
|
|
84
|
+
"subAgents",
|
|
85
|
+
index,
|
|
86
|
+
"name"
|
|
87
|
+
],
|
|
88
|
+
message: "Sub-agent name must be different from parent agent name"
|
|
89
|
+
});
|
|
90
|
+
if (seenSubAgentNames.has(normalizedName)) {
|
|
91
|
+
ctx.addIssue({
|
|
92
|
+
code: "custom",
|
|
93
|
+
path: [
|
|
94
|
+
"subAgents",
|
|
95
|
+
index,
|
|
96
|
+
"name"
|
|
97
|
+
],
|
|
98
|
+
message: "Sub-agent names must be unique within the same parent agent"
|
|
99
|
+
});
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
seenSubAgentNames.add(normalizedName);
|
|
103
|
+
}
|
|
75
104
|
});
|
|
76
105
|
function validateAgentConfig(config) {
|
|
77
106
|
try {
|
|
@@ -41,6 +41,35 @@ const BaseAgentConfigSchema = z.object({
|
|
|
41
41
|
});
|
|
42
42
|
const AgentConfigSchema = BaseAgentConfigSchema.extend({
|
|
43
43
|
subAgents: z.array(BaseAgentConfigSchema).optional().describe("List of sub-agents that this agent can delegate to (each may include its own model override)")
|
|
44
|
+
}).superRefine((config, ctx)=>{
|
|
45
|
+
if (!config.subAgents || 0 === config.subAgents.length) return;
|
|
46
|
+
const parentName = config.name.trim().toLowerCase();
|
|
47
|
+
const seenSubAgentNames = new Set();
|
|
48
|
+
for (const [index, subAgent] of config.subAgents.entries()){
|
|
49
|
+
const normalizedName = subAgent.name.trim().toLowerCase();
|
|
50
|
+
if (normalizedName === parentName) ctx.addIssue({
|
|
51
|
+
code: "custom",
|
|
52
|
+
path: [
|
|
53
|
+
"subAgents",
|
|
54
|
+
index,
|
|
55
|
+
"name"
|
|
56
|
+
],
|
|
57
|
+
message: "Sub-agent name must be different from parent agent name"
|
|
58
|
+
});
|
|
59
|
+
if (seenSubAgentNames.has(normalizedName)) {
|
|
60
|
+
ctx.addIssue({
|
|
61
|
+
code: "custom",
|
|
62
|
+
path: [
|
|
63
|
+
"subAgents",
|
|
64
|
+
index,
|
|
65
|
+
"name"
|
|
66
|
+
],
|
|
67
|
+
message: "Sub-agent names must be unique within the same parent agent"
|
|
68
|
+
});
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
seenSubAgentNames.add(normalizedName);
|
|
72
|
+
}
|
|
44
73
|
});
|
|
45
74
|
function validateAgentConfig(config) {
|
|
46
75
|
try {
|
|
@@ -69,6 +69,45 @@ const agentConfig_cjs_namespaceObject = require("../config/agentConfig.cjs");
|
|
|
69
69
|
(0, external_vitest_namespaceObject.expect)(result.success).toBe(true);
|
|
70
70
|
if (result.success) (0, external_vitest_namespaceObject.expect)(result.data.subAgents?.[0].model).toBe("openai:gpt-4o");
|
|
71
71
|
});
|
|
72
|
+
(0, external_vitest_namespaceObject.it)("should fail when a sub-agent shares the same name as its parent", ()=>{
|
|
73
|
+
const config = {
|
|
74
|
+
name: "coding",
|
|
75
|
+
description: "Parent coding agent",
|
|
76
|
+
systemPrompt: "You are the parent coding agent",
|
|
77
|
+
subAgents: [
|
|
78
|
+
{
|
|
79
|
+
name: "coding",
|
|
80
|
+
description: "Nested coding worker",
|
|
81
|
+
systemPrompt: "You are a worker"
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
};
|
|
85
|
+
const result = (0, agentConfig_cjs_namespaceObject.validateAgentConfig)(config);
|
|
86
|
+
(0, external_vitest_namespaceObject.expect)(result.success).toBe(false);
|
|
87
|
+
if (!result.success) (0, external_vitest_namespaceObject.expect)(result.error).toContain("Sub-agent name must be different from parent agent name");
|
|
88
|
+
});
|
|
89
|
+
(0, external_vitest_namespaceObject.it)("should fail when sub-agent names are duplicated", ()=>{
|
|
90
|
+
const config = {
|
|
91
|
+
name: "parent-agent",
|
|
92
|
+
description: "Parent agent",
|
|
93
|
+
systemPrompt: "You are the parent agent",
|
|
94
|
+
subAgents: [
|
|
95
|
+
{
|
|
96
|
+
name: "implementor",
|
|
97
|
+
description: "First implementor",
|
|
98
|
+
systemPrompt: "You implement changes"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: "IMPLEMENTOR",
|
|
102
|
+
description: "Duplicate implementor",
|
|
103
|
+
systemPrompt: "You implement more changes"
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
};
|
|
107
|
+
const result = (0, agentConfig_cjs_namespaceObject.validateAgentConfig)(config);
|
|
108
|
+
(0, external_vitest_namespaceObject.expect)(result.success).toBe(false);
|
|
109
|
+
if (!result.success) (0, external_vitest_namespaceObject.expect)(result.error).toContain("Sub-agent names must be unique within the same parent agent");
|
|
110
|
+
});
|
|
72
111
|
(0, external_vitest_namespaceObject.it)("should fail validation for missing required fields", ()=>{
|
|
73
112
|
const config = {
|
|
74
113
|
name: "test-agent"
|