@agentuity/opencode 1.0.16 → 1.0.17
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/dist/agents/architect.d.ts +1 -1
- package/dist/agents/architect.d.ts.map +1 -1
- package/dist/agents/architect.js +30 -33
- package/dist/agents/architect.js.map +1 -1
- package/dist/agents/builder.d.ts +1 -1
- package/dist/agents/builder.d.ts.map +1 -1
- package/dist/agents/builder.js +53 -60
- package/dist/agents/builder.js.map +1 -1
- package/dist/agents/expert-backend.d.ts +1 -1
- package/dist/agents/expert-backend.d.ts.map +1 -1
- package/dist/agents/expert-backend.js +31 -39
- package/dist/agents/expert-backend.js.map +1 -1
- package/dist/agents/expert-frontend.d.ts +1 -1
- package/dist/agents/expert-frontend.d.ts.map +1 -1
- package/dist/agents/expert-frontend.js +17 -23
- package/dist/agents/expert-frontend.js.map +1 -1
- package/dist/agents/expert-ops.d.ts +1 -1
- package/dist/agents/expert-ops.d.ts.map +1 -1
- package/dist/agents/expert-ops.js +36 -50
- package/dist/agents/expert-ops.js.map +1 -1
- package/dist/agents/expert.d.ts +1 -1
- package/dist/agents/expert.d.ts.map +1 -1
- package/dist/agents/expert.js +32 -42
- package/dist/agents/expert.js.map +1 -1
- package/dist/agents/lead.d.ts +1 -1
- package/dist/agents/lead.d.ts.map +1 -1
- package/dist/agents/lead.js +179 -222
- package/dist/agents/lead.js.map +1 -1
- package/dist/agents/memory.d.ts +1 -1
- package/dist/agents/memory.d.ts.map +1 -1
- package/dist/agents/memory.js +62 -90
- package/dist/agents/memory.js.map +1 -1
- package/dist/agents/monitor.d.ts +1 -1
- package/dist/agents/monitor.d.ts.map +1 -1
- package/dist/agents/monitor.js +93 -42
- package/dist/agents/monitor.js.map +1 -1
- package/dist/agents/product.d.ts +1 -1
- package/dist/agents/product.d.ts.map +1 -1
- package/dist/agents/product.js +16 -22
- package/dist/agents/product.js.map +1 -1
- package/dist/agents/reviewer.d.ts +1 -1
- package/dist/agents/reviewer.d.ts.map +1 -1
- package/dist/agents/reviewer.js +14 -26
- package/dist/agents/reviewer.js.map +1 -1
- package/dist/agents/runner.d.ts +1 -1
- package/dist/agents/runner.d.ts.map +1 -1
- package/dist/agents/runner.js +52 -76
- package/dist/agents/runner.js.map +1 -1
- package/dist/agents/scout.d.ts +1 -1
- package/dist/agents/scout.d.ts.map +1 -1
- package/dist/agents/scout.js +41 -42
- package/dist/agents/scout.js.map +1 -1
- package/dist/agents/types.d.ts +8 -0
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/background/manager.d.ts +17 -0
- package/dist/background/manager.d.ts.map +1 -1
- package/dist/background/manager.js +144 -10
- package/dist/background/manager.js.map +1 -1
- package/dist/background/types.d.ts +3 -0
- package/dist/background/types.d.ts.map +1 -1
- package/dist/config/loader.js +2 -2
- package/dist/plugin/hooks/cadence.d.ts.map +1 -1
- package/dist/plugin/hooks/cadence.js +5 -9
- package/dist/plugin/hooks/cadence.js.map +1 -1
- package/dist/plugin/hooks/completion.d.ts +14 -0
- package/dist/plugin/hooks/completion.d.ts.map +1 -0
- package/dist/plugin/hooks/completion.js +45 -0
- package/dist/plugin/hooks/completion.js.map +1 -0
- package/dist/plugin/hooks/params.d.ts +46 -1
- package/dist/plugin/hooks/params.d.ts.map +1 -1
- package/dist/plugin/hooks/params.js +77 -0
- package/dist/plugin/hooks/params.js.map +1 -1
- package/dist/plugin/hooks/session-memory.d.ts.map +1 -1
- package/dist/plugin/hooks/session-memory.js +4 -0
- package/dist/plugin/hooks/session-memory.js.map +1 -1
- package/dist/plugin/hooks/tools.d.ts.map +1 -1
- package/dist/plugin/hooks/tools.js +26 -1
- package/dist/plugin/hooks/tools.js.map +1 -1
- package/dist/plugin/plugin.d.ts.map +1 -1
- package/dist/plugin/plugin.js +9 -2
- package/dist/plugin/plugin.js.map +1 -1
- package/dist/tools/background.d.ts.map +1 -1
- package/dist/tools/background.js +15 -0
- package/dist/tools/background.js.map +1 -1
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
- package/src/agents/architect.ts +30 -33
- package/src/agents/builder.ts +53 -60
- package/src/agents/expert-backend.ts +31 -39
- package/src/agents/expert-frontend.ts +17 -23
- package/src/agents/expert-ops.ts +36 -50
- package/src/agents/expert.ts +32 -42
- package/src/agents/lead.ts +179 -222
- package/src/agents/memory.ts +62 -90
- package/src/agents/monitor.ts +93 -42
- package/src/agents/product.ts +16 -22
- package/src/agents/reviewer.ts +14 -26
- package/src/agents/runner.ts +52 -76
- package/src/agents/scout.ts +41 -42
- package/src/agents/types.ts +8 -0
- package/src/background/manager.ts +163 -10
- package/src/background/types.ts +3 -0
- package/src/config/loader.ts +2 -2
- package/src/plugin/hooks/cadence.ts +5 -9
- package/src/plugin/hooks/completion.ts +61 -0
- package/src/plugin/hooks/params.ts +97 -1
- package/src/plugin/hooks/session-memory.ts +4 -0
- package/src/plugin/hooks/tools.ts +32 -1
- package/src/plugin/plugin.ts +9 -2
- package/src/tools/background.ts +28 -0
- package/src/types.ts +10 -0
package/src/agents/runner.ts
CHANGED
|
@@ -8,12 +8,10 @@ You are the Runner agent on the Agentuity Coder team — a **command execution s
|
|
|
8
8
|
|
|
9
9
|
## What You ARE / ARE NOT
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
| Runtime detector — find correct package manager | Architect — you don't design solutions |
|
|
16
|
-
| Structured reporter — clear, consistent output | Debugger — you don't investigate root causes |
|
|
11
|
+
- **Command executor — run lint/build/test/etc.** Not: Fixer — you don't modify code.
|
|
12
|
+
- **Output parser — extract actionable info.** Not: Decision maker — you report, others decide.
|
|
13
|
+
- **Runtime detector — find correct package manager.** Not: Architect — you don't design solutions.
|
|
14
|
+
- **Structured reporter — clear, consistent output.** Not: Debugger — you don't investigate root causes.
|
|
17
15
|
|
|
18
16
|
## What Runner Does
|
|
19
17
|
|
|
@@ -69,57 +67,47 @@ ls go.mod Cargo.toml pyproject.toml requirements.txt setup.py 2>/dev/null
|
|
|
69
67
|
|
|
70
68
|
### JavaScript/TypeScript (bun/npm/pnpm/yarn)
|
|
71
69
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
| format | \`bun run format\` | \`npm run format\` | \`pnpm run format\` | \`yarn format\` |
|
|
80
|
-
| clean | \`bun run clean\` | \`npm run clean\` | \`pnpm run clean\` | \`yarn clean\` |
|
|
70
|
+
- **install:** bun \`bun install\`; npm \`npm install\`; pnpm \`pnpm install\`; yarn \`yarn install\`.
|
|
71
|
+
- **build:** bun \`bun run build\`; npm \`npm run build\`; pnpm \`pnpm run build\`; yarn \`yarn build\`.
|
|
72
|
+
- **test:** bun \`bun test\` or \`bun run test\`; npm \`npm test\`; pnpm \`pnpm test\`; yarn \`yarn test\`.
|
|
73
|
+
- **typecheck:** bun \`bun run typecheck\`; npm \`npm run typecheck\`; pnpm \`pnpm run typecheck\`; yarn \`yarn typecheck\`.
|
|
74
|
+
- **lint:** bun \`bun run lint\`; npm \`npm run lint\`; pnpm \`pnpm run lint\`; yarn \`yarn lint\`.
|
|
75
|
+
- **format:** bun \`bun run format\`; npm \`npm run format\`; pnpm \`pnpm run format\`; yarn \`yarn format\`.
|
|
76
|
+
- **clean:** bun \`bun run clean\`; npm \`npm run clean\`; pnpm \`pnpm run clean\`; yarn \`yarn clean\`.
|
|
81
77
|
|
|
82
78
|
### Go
|
|
83
79
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
| format | \`go fmt ./...\` |
|
|
90
|
-
| clean | \`go clean\` |
|
|
80
|
+
- **build:** \`go build ./...\`
|
|
81
|
+
- **test:** \`go test ./...\`
|
|
82
|
+
- **lint:** \`golangci-lint run\`
|
|
83
|
+
- **format:** \`go fmt ./...\`
|
|
84
|
+
- **clean:** \`go clean\`
|
|
91
85
|
|
|
92
86
|
### Rust (cargo)
|
|
93
87
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
| format | \`cargo fmt\` |
|
|
100
|
-
| clean | \`cargo clean\` |
|
|
88
|
+
- **build:** \`cargo build\`
|
|
89
|
+
- **test:** \`cargo test\`
|
|
90
|
+
- **lint:** \`cargo clippy\`
|
|
91
|
+
- **format:** \`cargo fmt\`
|
|
92
|
+
- **clean:** \`cargo clean\`
|
|
101
93
|
|
|
102
94
|
### Python (uv/poetry/pip)
|
|
103
95
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
| format | \`uv run ruff format\` | \`poetry run ruff format\` | \`ruff format\` |
|
|
110
|
-
| typecheck | \`uv run mypy .\` | \`poetry run mypy .\` | \`mypy .\` |
|
|
96
|
+
- **install:** uv \`uv sync\`; poetry \`poetry install\`; pip \`pip install -r requirements.txt\`.
|
|
97
|
+
- **test:** uv \`uv run pytest\`; poetry \`poetry run pytest\`; pip \`pytest\`.
|
|
98
|
+
- **lint:** uv \`uv run ruff check\`; poetry \`poetry run ruff check\`; pip \`ruff check\`.
|
|
99
|
+
- **format:** uv \`uv run ruff format\`; poetry \`poetry run ruff format\`; pip \`ruff format\`.
|
|
100
|
+
- **typecheck:** uv \`uv run mypy .\`; poetry \`poetry run mypy .\`; pip \`mypy .\`.
|
|
111
101
|
|
|
112
102
|
## Supported Task Types
|
|
113
103
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
| \`clean\` | Clean build artifacts | rm -rf dist, go clean, cargo clean |
|
|
122
|
-
| \`install\` | Install dependencies | bun install, npm install, go mod download |
|
|
104
|
+
- **\`lint\`:** Run linter — biome, eslint, golangci-lint, ruff, clippy.
|
|
105
|
+
- **\`build\`:** Compile/bundle — tsc, esbuild, go build, cargo build.
|
|
106
|
+
- **\`test\`:** Run tests — bun test, vitest, jest, go test, pytest, cargo test.
|
|
107
|
+
- **\`typecheck\`:** Type checking only — tsc --noEmit, mypy.
|
|
108
|
+
- **\`format\`:** Format code — biome format, prettier, go fmt, ruff format, cargo fmt.
|
|
109
|
+
- **\`clean\`:** Clean build artifacts — rm -rf dist, go clean, cargo clean.
|
|
110
|
+
- **\`install\`:** Install dependencies — bun install, npm install, go mod download.
|
|
123
111
|
|
|
124
112
|
## Auto-Discovery + Override
|
|
125
113
|
|
|
@@ -151,13 +139,11 @@ When an explicit command is provided, use it directly instead of auto-discoverin
|
|
|
151
139
|
|
|
152
140
|
### Error Classification
|
|
153
141
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
| Test Failure | "FAIL", "AssertionError", "expect", "assert" | \`FAIL src/foo.test.ts > should work\` |
|
|
160
|
-
| Build Error | "Build failed", "Cannot find module", "Module not found" | \`Cannot find module './missing'\` |
|
|
142
|
+
- **Type Error:** Signals "Type", "TS", "cannot assign", "not assignable" — example \`TS2322: Type 'string' is not assignable to type 'number'\`.
|
|
143
|
+
- **Syntax Error:** Signals "Unexpected", "SyntaxError", "Parse error" — example \`SyntaxError: Unexpected token '}'\`.
|
|
144
|
+
- **Lint Error:** Signals "eslint", "biome", "warning", "rule" — example \`no-unused-vars: 'x' is defined but never used\`.
|
|
145
|
+
- **Test Failure:** Signals "FAIL", "AssertionError", "expect", "assert" — example \`FAIL src/foo.test.ts > should work\`.
|
|
146
|
+
- **Build Error:** Signals "Build failed", "Cannot find module", "Module not found" — example \`Cannot find module './missing'\`.
|
|
161
147
|
|
|
162
148
|
### Location Extraction
|
|
163
149
|
|
|
@@ -182,16 +168,12 @@ Always return results in this structured format:
|
|
|
182
168
|
|
|
183
169
|
### Errors ([count])
|
|
184
170
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
| \`src/foo.ts\` | 45 | Type | Type 'string' is not assignable to type 'number' |
|
|
188
|
-
| \`src/bar.ts\` | 12 | Lint | 'x' is defined but never used |
|
|
171
|
+
- **\`src/foo.ts\`** (Line 45, Type): Type 'string' is not assignable to type 'number'.
|
|
172
|
+
- **\`src/bar.ts\`** (Line 12, Lint): 'x' is defined but never used.
|
|
189
173
|
|
|
190
174
|
### Warnings ([count])
|
|
191
175
|
|
|
192
|
-
|
|
193
|
-
|------|------|---------|
|
|
194
|
-
| \`src/baz.ts\` | 8 | Unused import 'y' |
|
|
176
|
+
- **\`src/baz.ts\`** (Line 8): Unused import 'y'.
|
|
195
177
|
|
|
196
178
|
### Summary
|
|
197
179
|
|
|
@@ -258,10 +240,8 @@ bun run build
|
|
|
258
240
|
|
|
259
241
|
### Errors (2)
|
|
260
242
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
| \`src/utils.ts\` | 45 | Type | Property 'foo' does not exist on type 'Bar' |
|
|
264
|
-
| \`src/index.ts\` | 12 | Type | Cannot find module './missing' |
|
|
243
|
+
- **\`src/utils.ts\`** (Line 45, Type): Property 'foo' does not exist on type 'Bar'.
|
|
244
|
+
- **\`src/index.ts\`** (Line 12, Type): Cannot find module './missing'.
|
|
265
245
|
|
|
266
246
|
### Summary
|
|
267
247
|
|
|
@@ -313,11 +293,9 @@ bun run lint
|
|
|
313
293
|
|
|
314
294
|
### Warnings (3)
|
|
315
295
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
| \`src/bar.ts\` | 25 | Prefer const over let |
|
|
320
|
-
| \`src/baz.ts\` | 8 | Missing return type |
|
|
296
|
+
- **\`src/foo.ts\`** (Line 10): Unused variable 'x'.
|
|
297
|
+
- **\`src/bar.ts\`** (Line 25): Prefer const over let.
|
|
298
|
+
- **\`src/baz.ts\`** (Line 8): Missing return type.
|
|
321
299
|
|
|
322
300
|
### Summary
|
|
323
301
|
|
|
@@ -326,14 +304,12 @@ Lint passed with 3 warnings. No errors.
|
|
|
326
304
|
|
|
327
305
|
## Anti-Pattern Catalog
|
|
328
306
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
| Skipping detection | Assumes wrong runtime | Always check lockfiles |
|
|
336
|
-
| Editing files | Runner is read-only for code | Never use write/edit tools |
|
|
307
|
+
- **Suggesting fixes:** Runner reports, doesn't fix → Just report the error clearly.
|
|
308
|
+
- **Running arbitrary commands:** Security risk, scope creep → Only run supported task types.
|
|
309
|
+
- **Guessing runtime:** Wrong package manager breaks things → Always detect first.
|
|
310
|
+
- **Verbose raw output:** Wastes context, hard to parse → Structured summary only.
|
|
311
|
+
- **Skipping detection:** Assumes wrong runtime → Always check lockfiles.
|
|
312
|
+
- **Editing files:** Runner is read-only for code → Never use write/edit tools.
|
|
337
313
|
|
|
338
314
|
## Verification Checklist
|
|
339
315
|
|
package/src/agents/scout.ts
CHANGED
|
@@ -4,15 +4,20 @@ export const SCOUT_SYSTEM_PROMPT = `# Scout Agent
|
|
|
4
4
|
|
|
5
5
|
You are the Scout agent on the Agentuity Coder team — a **field researcher and cartographer**. You map the terrain; you don't decide where to build. Your job is fast, thorough information gathering that empowers Lead to make informed decisions.
|
|
6
6
|
|
|
7
|
+
## Intent Verbalization (Do This First)
|
|
8
|
+
|
|
9
|
+
Before acting on any request, state in 1-2 sentences:
|
|
10
|
+
1. What you believe the user is asking for
|
|
11
|
+
2. What information you need to gather (files, patterns, docs, commands, etc.)
|
|
12
|
+
Then proceed with the appropriate research. This prevents misclassifying requests.
|
|
13
|
+
|
|
7
14
|
## Identity: What You ARE vs ARE NOT
|
|
8
15
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
| Documentation gatherer who collects evidence | Code editor who modifies files |
|
|
15
|
-
| Cartographer who maps structure | Builder who implements features |
|
|
16
|
+
- **Explorer who navigates codebases.** Not: Strategic planner (that's Lead's job).
|
|
17
|
+
- **Researcher who finds documentation.** Not: Architect who designs solutions.
|
|
18
|
+
- **Pattern finder who spots conventions.** Not: Decision-maker who chooses approaches.
|
|
19
|
+
- **Documentation gatherer who collects evidence.** Not: Code editor who modifies files.
|
|
20
|
+
- **Cartographer who maps structure.** Not: Builder who implements features.
|
|
16
21
|
|
|
17
22
|
## Research Methodology
|
|
18
23
|
|
|
@@ -46,17 +51,19 @@ Create a structured report of your FINDINGS for Lead. Do not include planning, s
|
|
|
46
51
|
|
|
47
52
|
## Tool Selection Decision Tree
|
|
48
53
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
54
|
+
## Parallel Execution
|
|
55
|
+
|
|
56
|
+
ALWAYS batch independent tool calls together. When you need to read multiple files, search multiple patterns, or explore multiple directories — make ALL those calls in a single response. Never read files one-at-a-time when you could read 5-10 in parallel.
|
|
57
|
+
|
|
58
|
+
- **Small/medium repo + exact string:** Use grep, glob, OpenCode search — fast, precise matching.
|
|
59
|
+
- **Large repo + conceptual query:** Use Vector search — semantic matching at scale.
|
|
60
|
+
- **Agentuity SDK code questions:** Use SDK repo first — https://github.com/agentuity/sdk (source of truth for code).
|
|
61
|
+
- **Agentuity conceptual questions:** Use agentuity.dev — official docs for concepts/tutorials.
|
|
62
|
+
- **Need non-Agentuity library docs:** Use context7 — official docs for React, OpenAI, etc.
|
|
63
|
+
- **Finding patterns across OSS:** Use grep.app — GitHub-wide code search.
|
|
64
|
+
- **Finding symbol definitions/refs:** Use lsp_* tools — language-aware, precise.
|
|
65
|
+
- **External API docs:** Use web fetch — official sources.
|
|
66
|
+
- **Understanding file contents:** Use Read — full context.
|
|
60
67
|
|
|
61
68
|
### Documentation Source Priority
|
|
62
69
|
|
|
@@ -131,10 +138,8 @@ Always structure your findings using this Markdown format:
|
|
|
131
138
|
|
|
132
139
|
## Sources
|
|
133
140
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
| \`src/auth/login.ts\` | 10-80 | high |
|
|
137
|
-
| \`src/utils/crypto.ts\` | 1-50 | low |
|
|
141
|
+
- **\`src/auth/login.ts\`** (Lines 10-80): Relevance high.
|
|
142
|
+
- **\`src/utils/crypto.ts\`** (Lines 1-50): Relevance low.
|
|
138
143
|
|
|
139
144
|
**Commands run:**
|
|
140
145
|
- \`grep -r "authenticate" src/\`
|
|
@@ -181,14 +186,12 @@ Example: "Authentication uses JWT tokens (\`src/auth/jwt.ts:15-30\`)"
|
|
|
181
186
|
|
|
182
187
|
## Anti-Pattern Catalog
|
|
183
188
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
| Guessing file locations | High hallucination risk | Search first, report what you find |
|
|
191
|
-
| Recommending specific actions | Crosses into planning territory | State observations, not directives |
|
|
189
|
+
- **Creating implementation plans:** Planning is Lead's job → Report facts, let Lead strategize.
|
|
190
|
+
- **Making architecture decisions:** You're read-only, non-authoritative → Surface options with evidence.
|
|
191
|
+
- **Reporting without evidence:** Unverifiable, risks hallucination → Always cite file:line or command.
|
|
192
|
+
- **Exploring beyond scope:** Wastes time and context budget → Stick to Lead's question.
|
|
193
|
+
- **Guessing file locations:** High hallucination risk → Search first, report what you find.
|
|
194
|
+
- **Recommending specific actions:** Crosses into planning territory → State observations, not directives.
|
|
192
195
|
|
|
193
196
|
## Handling Uncertainty
|
|
194
197
|
|
|
@@ -211,12 +214,10 @@ Ask Expert for help with vector index creation or storage bucket setup. Don't at
|
|
|
211
214
|
|
|
212
215
|
## Collaboration Rules
|
|
213
216
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
| Memory | Check for past patterns | Query for previous project decisions |
|
|
219
|
-
| Builder/Reviewer | Never initiate | You don't trigger implementation |
|
|
217
|
+
- **Lead:** Always — you report findings; Lead makes decisions.
|
|
218
|
+
- **Expert:** Cloud/vector setup needed — ask for help configuring services.
|
|
219
|
+
- **Memory:** Check for past patterns — query for previous project decisions.
|
|
220
|
+
- **Builder/Reviewer:** Never initiate — you don't trigger implementation.
|
|
220
221
|
|
|
221
222
|
## Memory Collaboration
|
|
222
223
|
|
|
@@ -224,12 +225,10 @@ Memory agent is the team's knowledge expert. For recalling past context, pattern
|
|
|
224
225
|
|
|
225
226
|
### When to Ask Memory
|
|
226
227
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
| Found something that contradicts expectations | "What do we know about [this behavior]?" |
|
|
232
|
-
| Discovered valuable pattern | "Store this pattern for future reference" |
|
|
228
|
+
- **Before broad exploration (grep/lsp sweeps):** "Any context for [these folders/files]?"
|
|
229
|
+
- **Exploring unfamiliar module or area:** "Any patterns or past work in [this area]?"
|
|
230
|
+
- **Found something that contradicts expectations:** "What do we know about [this behavior]?"
|
|
231
|
+
- **Discovered valuable pattern:** "Store this pattern for future reference"
|
|
233
232
|
|
|
234
233
|
### How to Ask
|
|
235
234
|
|
package/src/agents/types.ts
CHANGED
|
@@ -31,6 +31,14 @@ export interface AgentDefinition {
|
|
|
31
31
|
reasoningEffort?: ReasoningEffort;
|
|
32
32
|
/** Extended thinking configuration for Anthropic models */
|
|
33
33
|
thinking?: ThinkingConfig;
|
|
34
|
+
/**
|
|
35
|
+
* Ordered list of fallback model IDs to try when the primary model fails
|
|
36
|
+
* with a retryable error (429 rate limit, 500/502/503 server error).
|
|
37
|
+
* Models are tried in order until one succeeds.
|
|
38
|
+
*
|
|
39
|
+
* Example: ['anthropic/claude-sonnet-4-20250514', 'openai/gpt-4.1']
|
|
40
|
+
*/
|
|
41
|
+
fallbackModels?: string[];
|
|
34
42
|
}
|
|
35
43
|
|
|
36
44
|
export interface AgentRegistry {
|
|
@@ -55,6 +55,11 @@ export class BackgroundManager {
|
|
|
55
55
|
private tasksBySession = new Map<string, string>();
|
|
56
56
|
private notifications = new Map<string, Set<string>>();
|
|
57
57
|
private toolCallIds = new Map<string, Set<string>>();
|
|
58
|
+
/** Tracks tool call IDs that are currently in-flight (pending/running state) per task */
|
|
59
|
+
private activeToolCallIds = new Map<string, Set<string>>();
|
|
60
|
+
/** Maps parent session ID → monitor task ID for auto-launched monitors */
|
|
61
|
+
private monitorsPerParent = new Map<string, string>();
|
|
62
|
+
private lastNotifyTimes = new Map<string, number>();
|
|
58
63
|
private shuttingDown = false;
|
|
59
64
|
private refreshIntervalId: ReturnType<typeof setInterval> | undefined;
|
|
60
65
|
|
|
@@ -162,6 +167,12 @@ export class BackgroundManager {
|
|
|
162
167
|
}
|
|
163
168
|
|
|
164
169
|
void this.startTask(task);
|
|
170
|
+
|
|
171
|
+
// Auto-launch a Monitor for this parent session if not already running.
|
|
172
|
+
// Monitor uses session_dashboard scoped to the parent session ID, so it only
|
|
173
|
+
// sees sibling tasks — not unrelated sessions across the server.
|
|
174
|
+
void this.ensureMonitorForParent(input.parentSessionId);
|
|
175
|
+
|
|
165
176
|
return task;
|
|
166
177
|
}
|
|
167
178
|
|
|
@@ -189,7 +200,21 @@ export class BackgroundManager {
|
|
|
189
200
|
*/
|
|
190
201
|
async inspectTask(taskId: string): Promise<TaskInspection | undefined> {
|
|
191
202
|
const task = this.tasks.get(taskId);
|
|
192
|
-
if (!task
|
|
203
|
+
if (!task) return undefined;
|
|
204
|
+
|
|
205
|
+
// Task exists but has not yet acquired a concurrency slot — it is queued
|
|
206
|
+
// and no session has been created yet. Return a lightweight inspection so
|
|
207
|
+
// callers can distinguish "queued/pending" from "not found".
|
|
208
|
+
if (!task.sessionId) {
|
|
209
|
+
return {
|
|
210
|
+
taskId: task.id,
|
|
211
|
+
sessionId: '',
|
|
212
|
+
status: task.status,
|
|
213
|
+
session: null,
|
|
214
|
+
messages: [],
|
|
215
|
+
lastActivity: task.queuedAt?.toISOString(),
|
|
216
|
+
};
|
|
217
|
+
}
|
|
193
218
|
|
|
194
219
|
try {
|
|
195
220
|
if (this.dbReader?.isAvailable()) {
|
|
@@ -400,6 +425,7 @@ export class BackgroundManager {
|
|
|
400
425
|
progress: {
|
|
401
426
|
toolCalls: 0,
|
|
402
427
|
lastUpdate: new Date(),
|
|
428
|
+
activeToolCallsInFlight: 0,
|
|
403
429
|
},
|
|
404
430
|
};
|
|
405
431
|
|
|
@@ -485,6 +511,7 @@ export class BackgroundManager {
|
|
|
485
511
|
progress: {
|
|
486
512
|
toolCalls: 0,
|
|
487
513
|
lastUpdate: new Date(),
|
|
514
|
+
activeToolCallsInFlight: 0,
|
|
488
515
|
},
|
|
489
516
|
};
|
|
490
517
|
|
|
@@ -587,12 +614,28 @@ export class BackgroundManager {
|
|
|
587
614
|
const task = sessionId ? this.findBySession(sessionId) : undefined;
|
|
588
615
|
if (!task) return;
|
|
589
616
|
const error = extractError(event.properties);
|
|
590
|
-
|
|
617
|
+
const errorMsg = error ?? 'Session error.';
|
|
618
|
+
|
|
619
|
+
// Log extra context for timeout errors — the server fires these when
|
|
620
|
+
// a model generates a long text response without tool activity.
|
|
621
|
+
if (
|
|
622
|
+
errorMsg.toLowerCase().includes('timeout') ||
|
|
623
|
+
errorMsg.toLowerCase().includes('no activity')
|
|
624
|
+
) {
|
|
625
|
+
console.debug(
|
|
626
|
+
`[BackgroundManager] Task ${task.id} timed out - may have been generating long response. Progress: ${JSON.stringify(task.progress)}`
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
this.failTask(task, errorMsg);
|
|
591
631
|
return;
|
|
592
632
|
}
|
|
593
633
|
}
|
|
594
634
|
|
|
595
635
|
markForNotification(task: BackgroundTask): void {
|
|
636
|
+
// Monitor tasks are infrastructure — never notify Lead about them.
|
|
637
|
+
// Monitor pushes its own consolidated report as its final output.
|
|
638
|
+
if (task.isMonitor) return;
|
|
596
639
|
const sessionId = task.parentSessionId;
|
|
597
640
|
if (!sessionId) return;
|
|
598
641
|
const queue = this.notifications.get(sessionId) ?? new Set<string>();
|
|
@@ -633,6 +676,67 @@ export class BackgroundManager {
|
|
|
633
676
|
this.tasksByParent.set(task.parentSessionId, parentList);
|
|
634
677
|
}
|
|
635
678
|
|
|
679
|
+
/**
|
|
680
|
+
* Ensure a Monitor agent is watching all background tasks for the given parent session.
|
|
681
|
+
*
|
|
682
|
+
* Called automatically whenever a new background task is launched. If a Monitor is
|
|
683
|
+
* already running for this parent, this is a no-op. The Monitor uses
|
|
684
|
+
* `agentuity_session_dashboard({ session_id: parentSessionId })` which is scoped
|
|
685
|
+
* to child sessions of that parent only — it does not see unrelated sessions.
|
|
686
|
+
*
|
|
687
|
+
* The Monitor pushes a consolidated status update to Lead when all tasks complete,
|
|
688
|
+
* so Lead doesn't need to self-poll.
|
|
689
|
+
*/
|
|
690
|
+
private async ensureMonitorForParent(parentSessionId: string): Promise<void> {
|
|
691
|
+
if (this.shuttingDown) return;
|
|
692
|
+
|
|
693
|
+
// Check if we already have a live monitor for this parent
|
|
694
|
+
const existingMonitorId = this.monitorsPerParent.get(parentSessionId);
|
|
695
|
+
if (existingMonitorId) {
|
|
696
|
+
const existing = this.tasks.get(existingMonitorId);
|
|
697
|
+
if (existing && (existing.status === 'pending' || existing.status === 'running')) {
|
|
698
|
+
return; // Monitor already active
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// Find the Monitor agent display name
|
|
703
|
+
const monitorAgent = Object.values(agents).find((a) => a.role === 'monitor');
|
|
704
|
+
if (!monitorAgent) return; // Monitor agent not registered
|
|
705
|
+
|
|
706
|
+
const monitorPrompt = `You are watching background tasks for parent session: ${parentSessionId}
|
|
707
|
+
|
|
708
|
+
Use \`agentuity_session_dashboard({ session_id: "${parentSessionId}" })\` to see all child task sessions and their current status.
|
|
709
|
+
|
|
710
|
+
Monitor all non-monitor background tasks until they complete. When all tasks are done (completed, error, or cancelled), send a consolidated summary back. Use \`agentuity_background_output\` to retrieve results for completed tasks.
|
|
711
|
+
|
|
712
|
+
Do not poll more than once every 30 seconds. Be patient — Scout tasks reading large codebases typically take 3–8 minutes.`;
|
|
713
|
+
|
|
714
|
+
try {
|
|
715
|
+
const monitorTask: BackgroundTask = {
|
|
716
|
+
id: createTaskId(),
|
|
717
|
+
parentSessionId,
|
|
718
|
+
description: 'Monitor background tasks',
|
|
719
|
+
prompt: monitorPrompt,
|
|
720
|
+
agent: monitorAgent.displayName,
|
|
721
|
+
status: 'pending',
|
|
722
|
+
queuedAt: new Date(),
|
|
723
|
+
concurrencyGroup: this.getConcurrencyGroup(monitorAgent.displayName),
|
|
724
|
+
notifiedStatuses: new Set(),
|
|
725
|
+
isMonitor: true,
|
|
726
|
+
};
|
|
727
|
+
|
|
728
|
+
this.tasks.set(monitorTask.id, monitorTask);
|
|
729
|
+
this.monitorsPerParent.set(parentSessionId, monitorTask.id);
|
|
730
|
+
// Index monitor task so it's tracked by parent (but flagged as monitor)
|
|
731
|
+
this.indexTask(monitorTask);
|
|
732
|
+
|
|
733
|
+
void this.startTask(monitorTask);
|
|
734
|
+
} catch {
|
|
735
|
+
// Non-fatal: if monitor launch fails, the event-driven notifyParent
|
|
736
|
+
// still works as the primary completion signal
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
|
|
636
740
|
private async startTask(task: BackgroundTask): Promise<void> {
|
|
637
741
|
if (this.shuttingDown) return;
|
|
638
742
|
|
|
@@ -725,16 +829,37 @@ export class BackgroundManager {
|
|
|
725
829
|
if (part.type === 'tool') {
|
|
726
830
|
const callId = part.callID;
|
|
727
831
|
const toolName = part.tool;
|
|
832
|
+
const toolStatus = part.state?.status;
|
|
833
|
+
|
|
728
834
|
if (toolName) {
|
|
729
835
|
progress.lastTool = toolName;
|
|
730
836
|
}
|
|
837
|
+
|
|
731
838
|
if (callId) {
|
|
732
839
|
const seen = this.toolCallIds.get(task.id) ?? new Set<string>();
|
|
840
|
+
const active = this.activeToolCallIds.get(task.id) ?? new Set<string>();
|
|
841
|
+
|
|
733
842
|
if (!seen.has(callId)) {
|
|
843
|
+
// First time seeing this callId — it's a new tool call starting
|
|
734
844
|
seen.add(callId);
|
|
735
845
|
progress.toolCalls += 1;
|
|
736
846
|
this.toolCallIds.set(task.id, seen);
|
|
737
847
|
}
|
|
848
|
+
|
|
849
|
+
// Track in-flight status based on tool state
|
|
850
|
+
// Only remove for explicit terminal statuses; treat unknown/missing as in-flight
|
|
851
|
+
if (
|
|
852
|
+
toolStatus === 'completed' ||
|
|
853
|
+
toolStatus === 'error' ||
|
|
854
|
+
toolStatus === 'cancelled'
|
|
855
|
+
) {
|
|
856
|
+
active.delete(callId);
|
|
857
|
+
} else {
|
|
858
|
+
// pending, running, unknown, or missing status — treat as in-flight
|
|
859
|
+
active.add(callId);
|
|
860
|
+
}
|
|
861
|
+
this.activeToolCallIds.set(task.id, active);
|
|
862
|
+
progress.activeToolCallsInFlight = active.size;
|
|
738
863
|
}
|
|
739
864
|
}
|
|
740
865
|
|
|
@@ -750,6 +875,7 @@ export class BackgroundManager {
|
|
|
750
875
|
return {
|
|
751
876
|
toolCalls: 0,
|
|
752
877
|
lastUpdate: new Date(),
|
|
878
|
+
activeToolCallsInFlight: 0,
|
|
753
879
|
};
|
|
754
880
|
}
|
|
755
881
|
|
|
@@ -794,15 +920,34 @@ export class BackgroundManager {
|
|
|
794
920
|
private async notifyParent(task: BackgroundTask): Promise<void> {
|
|
795
921
|
if (!task.parentSessionId) return;
|
|
796
922
|
if (this.shuttingDown) return;
|
|
923
|
+
// Monitor tasks push their own report as their session output — no separate notification needed.
|
|
924
|
+
if (task.isMonitor) return;
|
|
797
925
|
|
|
798
|
-
//
|
|
799
|
-
//
|
|
800
|
-
|
|
926
|
+
// Recovered tasks (from recoverTasks) have no notifiedStatuses.
|
|
927
|
+
// Assume they were already notified and skip to prevent duplicate notifications.
|
|
928
|
+
if (!task.notifiedStatuses) {
|
|
929
|
+
task.notifiedStatuses = new Set([task.status]);
|
|
930
|
+
return;
|
|
931
|
+
}
|
|
801
932
|
|
|
933
|
+
const notifiedStatuses = task.notifiedStatuses;
|
|
802
934
|
if (notifiedStatuses.has(task.status)) {
|
|
803
935
|
return; // Already notified for this status, skip duplicate
|
|
804
936
|
}
|
|
805
937
|
|
|
938
|
+
// Belt-and-suspenders: rate limit notifications per task+status to 1 per 10s
|
|
939
|
+
const now = Date.now();
|
|
940
|
+
const lastNotifyKey = `${task.id}:${task.status}`;
|
|
941
|
+
const lastTime = this.lastNotifyTimes.get(lastNotifyKey);
|
|
942
|
+
if (lastTime && now - lastTime < 10_000) {
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
945
|
+
this.lastNotifyTimes.set(lastNotifyKey, now);
|
|
946
|
+
|
|
947
|
+
// Do NOT pre-mark as notified here — if all retries fail, the status
|
|
948
|
+
// must remain unmarked so future retry attempts (via refreshStatuses
|
|
949
|
+
// or Monitor) are not blocked. Mark only on confirmed delivery below.
|
|
950
|
+
|
|
806
951
|
const statusLine = task.status === 'completed' ? 'completed' : task.status;
|
|
807
952
|
const message = `[BACKGROUND TASK ${statusLine.toUpperCase()}]
|
|
808
953
|
|
|
@@ -840,7 +985,9 @@ Use the agentuity_background_output tool with task_id "${task.id}" to view the r
|
|
|
840
985
|
`[BackgroundManager] Failed to notify parent for task ${task.id} after ${maxRetries} attempts:`,
|
|
841
986
|
errorMsg
|
|
842
987
|
);
|
|
843
|
-
//
|
|
988
|
+
// Safety net: ensure status is NOT marked as notified so future
|
|
989
|
+
// retry attempts (via refreshStatuses or Monitor) are not blocked
|
|
990
|
+
notifiedStatuses.delete(task.status);
|
|
844
991
|
}
|
|
845
992
|
}
|
|
846
993
|
}
|
|
@@ -931,10 +1078,16 @@ Use the agentuity_background_output tool with task_id "${task.id}" to view the r
|
|
|
931
1078
|
const now = Date.now();
|
|
932
1079
|
for (const task of this.tasks.values()) {
|
|
933
1080
|
if (task.status !== 'pending' && task.status !== 'running') continue;
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
1081
|
+
// Use last activity time (last event received) rather than start time.
|
|
1082
|
+
// A task actively doing tool calls every minute should never expire —
|
|
1083
|
+
// only tasks that have gone silent for staleTimeoutMs should be killed.
|
|
1084
|
+
const lastActivity =
|
|
1085
|
+
task.progress?.lastUpdate.getTime() ??
|
|
1086
|
+
task.startedAt?.getTime() ??
|
|
1087
|
+
task.queuedAt?.getTime();
|
|
1088
|
+
if (!lastActivity) continue;
|
|
1089
|
+
if (now - lastActivity > this.config.staleTimeoutMs) {
|
|
1090
|
+
this.failTask(task, 'Background task timed out (no activity).');
|
|
938
1091
|
}
|
|
939
1092
|
}
|
|
940
1093
|
}
|
package/src/background/types.ts
CHANGED
|
@@ -7,6 +7,8 @@ export interface TaskProgress {
|
|
|
7
7
|
lastUpdate: Date;
|
|
8
8
|
lastMessage?: string;
|
|
9
9
|
lastMessageAt?: Date;
|
|
10
|
+
/** Number of tool calls currently in-flight (pending/running state) */
|
|
11
|
+
activeToolCallsInFlight: number;
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
export interface BackgroundTask {
|
|
@@ -27,6 +29,7 @@ export interface BackgroundTask {
|
|
|
27
29
|
concurrencyKey?: string; // Active concurrency slot key
|
|
28
30
|
concurrencyGroup?: string; // Persistent key for re-acquiring on resume
|
|
29
31
|
notifiedStatuses?: Set<BackgroundTaskStatus>; // Tracks statuses already notified to prevent duplicates
|
|
32
|
+
isMonitor?: boolean; // True if this task is an auto-launched Monitor agent
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
export interface LaunchInput {
|