opencode-swarm 7.16.0 → 7.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/agents/index.d.ts +3 -2
- package/dist/agents/project-context.d.ts +58 -0
- package/dist/agents/template.d.ts +85 -0
- package/dist/build/discovery.d.ts +2 -4
- package/dist/cli/index.js +1768 -345
- package/dist/hooks/knowledge-injector.d.ts +2 -1
- package/dist/hooks/knowledge-types.d.ts +1 -1
- package/dist/hooks/knowledge-validator.d.ts +1 -0
- package/dist/index.js +2982 -1380
- package/dist/lang/backend.d.ts +199 -0
- package/dist/lang/backends/go.d.ts +21 -0
- package/dist/lang/backends/index.d.ts +27 -0
- package/dist/lang/backends/python.d.ts +25 -0
- package/dist/lang/backends/typescript.d.ts +56 -0
- package/dist/lang/default-backend.d.ts +105 -0
- package/dist/lang/dispatch.d.ts +52 -0
- package/dist/lang/profiles.d.ts +28 -0
- package/dist/lang/registry-backend.d.ts +35 -0
- package/dist/test-impact/analyzer.d.ts +7 -0
- package/dist/tools/test-runner.d.ts +22 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ Most AI coding tools let one model write code and ask that same model whether th
|
|
|
36
36
|
- 🔒 **Gated pipeline** — code never ships without reviewer + test engineer approval
|
|
37
37
|
- 🔄 **Phase completion gates** — completion-verify and drift verifier gates enforced before phase completion
|
|
38
38
|
- 🔁 **Resumable sessions** — all state saved to `.swarm/`; pick up any project any day
|
|
39
|
-
- 🌐 **20 languages** — TypeScript, Python, Go, Rust, Java, Kotlin, C/C++, C#, Ruby, Swift, Dart, PHP, JavaScript, CSS, Bash, PowerShell, INI, Regex
|
|
39
|
+
- 🌐 **20 languages** — TypeScript, Python, Go, Rust, Java, Kotlin, C/C++, C#, Ruby, Swift, Dart, PHP, JavaScript, CSS, Bash, PowerShell, INI, Regex (extending: see [docs/adding-a-language.md](docs/adding-a-language.md))
|
|
40
40
|
- 🛡️ **Built-in security** — SAST, secrets scanning, dependency audit per task
|
|
41
41
|
- 🆓 **Free tier** — works with OpenCode Zen's free model roster
|
|
42
42
|
- ⚙️ **Fully configurable** — override any agent's model, disable agents, tune guardrails
|
package/dist/agents/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AgentConfig as SDKAgentConfig } from '@opencode-ai/sdk';
|
|
2
2
|
import { type PluginConfig } from '../config';
|
|
3
3
|
import { type AgentDefinition } from './architect';
|
|
4
|
+
import { type ProjectContext } from './template';
|
|
4
5
|
export type { AgentDefinition } from './architect';
|
|
5
6
|
/**
|
|
6
7
|
* Strip the user-defined swarm prefix from an agent name to get the base
|
|
@@ -41,7 +42,7 @@ export declare function getSwarmAgents(): Record<string, {
|
|
|
41
42
|
/**
|
|
42
43
|
* Create all agent definitions with configuration applied
|
|
43
44
|
*/
|
|
44
|
-
export declare function createAgents(config?: PluginConfig): AgentDefinition[];
|
|
45
|
+
export declare function createAgents(config?: PluginConfig, projectContext?: ProjectContext): AgentDefinition[];
|
|
45
46
|
/**
|
|
46
47
|
* Resolve the set of generated agent names that should be marked as primary
|
|
47
48
|
* for OpenCode's session-default-agent resolution.
|
|
@@ -73,7 +74,7 @@ export declare function resolvePrimaryAgentNames(agentNames: string[], defaultAg
|
|
|
73
74
|
/**
|
|
74
75
|
* Get agent configurations formatted for the OpenCode SDK.
|
|
75
76
|
*/
|
|
76
|
-
export declare function getAgentConfigs(config?: PluginConfig, directory?: string, sessionId?: string): Record<string, SDKAgentConfig>;
|
|
77
|
+
export declare function getAgentConfigs(config?: PluginConfig, directory?: string, sessionId?: string, projectContext?: ProjectContext): Record<string, SDKAgentConfig>;
|
|
77
78
|
export { createArchitectAgent } from './architect';
|
|
78
79
|
export { createCoderAgent } from './coder';
|
|
79
80
|
export { DOMAIN_EXPERT_COUNCIL_PROMPT, GENERALIST_COUNCIL_PROMPT, SKEPTIC_COUNCIL_PROMPT, } from './council-prompts';
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a `ProjectContext` for agent prompt template substitution.
|
|
3
|
+
*
|
|
4
|
+
* Called from `src/index.ts:initializeOpenCodeSwarm` immediately before
|
|
5
|
+
* `getAgentConfigs(...)` (Phase 4b of the language-agnostic plugin work).
|
|
6
|
+
* Wrapped in `withTimeout(2000ms)` by the caller; on timeout or any
|
|
7
|
+
* failure, the caller falls open to `emptyProjectContext()` per
|
|
8
|
+
* Invariant 1 (plugin init bounded + fail-open).
|
|
9
|
+
*
|
|
10
|
+
* Imported lazily by the caller via `await import('./agents/project-context')`
|
|
11
|
+
* to keep the dispatch import graph off the synchronous init prelude.
|
|
12
|
+
*
|
|
13
|
+
* Invariant 1 budget — Phase 4b NOTE:
|
|
14
|
+
* This module DOES NOT spawn subprocesses on the session-init critical
|
|
15
|
+
* path. The full `LanguageBackend.selectTestFramework` /
|
|
16
|
+
* `selectBuildCommand` hooks call `isCommandAvailable` (which spawns
|
|
17
|
+
* `where`/`which` and can take 200–500ms per call on Windows). Even with
|
|
18
|
+
* the 2000ms `withTimeout` wrapper, multiple sequential spawns
|
|
19
|
+
* (typically 3–5 per buildProjectContext call) easily push `server()`
|
|
20
|
+
* past the 400ms Invariant 1 deadline asserted by
|
|
21
|
+
* `scripts/repro-704.mjs:TIMING_DEADLINE_MS`.
|
|
22
|
+
*
|
|
23
|
+
* The architect prompt's `TEST_CMD` / `BUILD_CMD` / `LINT_CMD` values are
|
|
24
|
+
* HINTS for the LLM. If the user doesn't have the named binary installed,
|
|
25
|
+
* the actual test-runner / build-runner tool will surface a clear error
|
|
26
|
+
* at invocation time — there is no correctness regression from skipping
|
|
27
|
+
* the PATH probe at session init.
|
|
28
|
+
*/
|
|
29
|
+
import { pickBackend, pickedProfiles } from '../lang/dispatch';
|
|
30
|
+
import { type ProjectContext } from './template';
|
|
31
|
+
/**
|
|
32
|
+
* Wall-clock budget for the session-init language-backend resolution step.
|
|
33
|
+
* Caller (`src/index.ts:initializeOpenCodeSwarm`) wraps `buildProjectContext`
|
|
34
|
+
* in `withTimeout(LANG_BACKEND_DETECTION_TIMEOUT_MS)`. Exceeding the budget
|
|
35
|
+
* fails open with `null` so the manifest still returns to the OpenCode
|
|
36
|
+
* plugin host (Invariant 1).
|
|
37
|
+
*/
|
|
38
|
+
export declare const LANG_BACKEND_DETECTION_TIMEOUT_MS = 300;
|
|
39
|
+
declare const _internals: {
|
|
40
|
+
pickBackend: typeof pickBackend;
|
|
41
|
+
pickedProfiles: typeof pickedProfiles;
|
|
42
|
+
};
|
|
43
|
+
export { _internals };
|
|
44
|
+
/**
|
|
45
|
+
* Resolve the `ProjectContext` for `directory`. Uses `pickBackend` to find
|
|
46
|
+
* the dominant language, then queries the backend's PROFILE DATA (not its
|
|
47
|
+
* spawn-bearing hooks) for build/test/lint commands. Calls the optional
|
|
48
|
+
* `selectFramework` and `selectEntryPoints` hooks because those are
|
|
49
|
+
* filesystem-only (no spawn) per the backend purity invariant.
|
|
50
|
+
*
|
|
51
|
+
* Per-backend constraint blocks (coder/test/reviewer) come from
|
|
52
|
+
* `backend.prompts` — pure data.
|
|
53
|
+
*
|
|
54
|
+
* Returns `null` (caller substitutes `emptyProjectContext()`) when no
|
|
55
|
+
* backend is detected — the architect's existing DISCOVER mode handles
|
|
56
|
+
* the resulting `unresolved` sentinel placeholders.
|
|
57
|
+
*/
|
|
58
|
+
export declare function buildProjectContext(directory: string): Promise<ProjectContext | null>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent prompt template renderer.
|
|
3
|
+
*
|
|
4
|
+
* Replaces `{{KEY}}` placeholders in agent prompt strings with values from
|
|
5
|
+
* a `ProjectContext` resolved at session-init time. Strict by design:
|
|
6
|
+
* unknown placeholders raise (caught at build time by
|
|
7
|
+
* `tests/unit/agents/template-substitution.test.ts`), so a typo never
|
|
8
|
+
* leaks to the model.
|
|
9
|
+
*
|
|
10
|
+
* Phase 4b of language-agnostic plugin work. Pinned call site is
|
|
11
|
+
* `src/index.ts:initializeOpenCodeSwarm` immediately before
|
|
12
|
+
* `getAgentConfigs(...)` — see the `withTimeout(2000ms)` wrapping there
|
|
13
|
+
* to honor invariant 1 (plugin init bounded + fail-open).
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Variables available for substitution into agent prompts. Every prompt's
|
|
17
|
+
* `{{KEY}}` placeholders must be a key of this interface; the renderer
|
|
18
|
+
* rejects unknown placeholders. New variables go here AND in
|
|
19
|
+
* `buildProjectContext` in `src/index.ts`.
|
|
20
|
+
*/
|
|
21
|
+
export interface ProjectContext {
|
|
22
|
+
PROJECT_LANGUAGE: string;
|
|
23
|
+
PROJECT_FRAMEWORK: string;
|
|
24
|
+
BUILD_CMD: string;
|
|
25
|
+
TEST_CMD: string;
|
|
26
|
+
LINT_CMD: string;
|
|
27
|
+
ENTRY_POINTS: string;
|
|
28
|
+
/**
|
|
29
|
+
* Per-language coder constraint bullets (already escaped for inclusion
|
|
30
|
+
* in a TypeScript template literal — see `escapeForTemplate`).
|
|
31
|
+
*/
|
|
32
|
+
CODER_CONSTRAINTS: string;
|
|
33
|
+
/** Per-language test-writing constraint bullets. */
|
|
34
|
+
TEST_CONSTRAINTS: string;
|
|
35
|
+
/** Per-language reviewer-checklist bullets. */
|
|
36
|
+
REVIEWER_CHECKLIST: string;
|
|
37
|
+
/**
|
|
38
|
+
* When backend detection finds multiple equal-tier languages, this is
|
|
39
|
+
* a comma-separated list of the runner-up language ids; empty string
|
|
40
|
+
* when only one language is detected.
|
|
41
|
+
*/
|
|
42
|
+
PROJECT_CONTEXT_SECONDARY_LANGUAGES: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Sentinel substituted into placeholders when the backend cannot resolve
|
|
46
|
+
* a value (no manifest, binary missing, detection timed out). The
|
|
47
|
+
* architect prompt's existing DISCOVER mode handles this — same contract
|
|
48
|
+
* as today, but the trigger is now a literal sentinel string rather than
|
|
49
|
+
* a templating leak.
|
|
50
|
+
*/
|
|
51
|
+
export declare const UNRESOLVED = "unresolved (run /swarm preflight)";
|
|
52
|
+
/** Empty `ProjectContext` — used by fail-open paths and tests. */
|
|
53
|
+
export declare function emptyProjectContext(): ProjectContext;
|
|
54
|
+
/**
|
|
55
|
+
* Escape a string for safe inclusion inside a TypeScript template literal.
|
|
56
|
+
* Specifically:
|
|
57
|
+
* - Backticks `` ` `` become `` \` `` (otherwise terminate the literal).
|
|
58
|
+
* - `${` becomes `\${` (otherwise begins an interpolation).
|
|
59
|
+
* - Backslashes are preserved as-is (template literals don't double-escape
|
|
60
|
+
* them when read at runtime — only at parse time, which we're past).
|
|
61
|
+
*
|
|
62
|
+
* See `.claude/skills/engineering-conventions/SKILL.md` "Agent prompt
|
|
63
|
+
* strings — escaping pitfalls" for context. Profile-author-supplied
|
|
64
|
+
* constraint strings (e.g. `LanguageProfile.prompts.coderConstraints`)
|
|
65
|
+
* routinely contain backticks (when describing code idioms like `bun:test`).
|
|
66
|
+
* The renderer auto-escapes them so a profile author can't accidentally
|
|
67
|
+
* break agent compilation.
|
|
68
|
+
*/
|
|
69
|
+
export declare function escapeForTemplate(s: string): string;
|
|
70
|
+
/**
|
|
71
|
+
* Render `prompt` with `vars`. Replaces every `{{KEY}}` whose KEY is a
|
|
72
|
+
* documented `ProjectContext` field. Unknown placeholders raise.
|
|
73
|
+
*
|
|
74
|
+
* The renderer is intentionally simple — single-pass, no nesting, no
|
|
75
|
+
* conditionals, no loops. Agent prompts that need conditional sections
|
|
76
|
+
* should pre-compute a string variable in `buildProjectContext` and
|
|
77
|
+
* substitute it as a single placeholder.
|
|
78
|
+
*/
|
|
79
|
+
export declare function renderPrompt(prompt: string, vars: ProjectContext): string;
|
|
80
|
+
/**
|
|
81
|
+
* Convert an array of constraint strings into a bulleted block ready for
|
|
82
|
+
* inclusion in an agent prompt via `{{CODER_CONSTRAINTS}}` etc.
|
|
83
|
+
* Each item is escaped for template-literal safety.
|
|
84
|
+
*/
|
|
85
|
+
export declare function bulletList(items: readonly string[]): string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { tool } from '@opencode-ai/plugin';
|
|
2
|
+
import { bunSpawnSync } from '../utils/bun-compat';
|
|
2
3
|
export interface BuildCommand {
|
|
3
4
|
ecosystem: string;
|
|
4
5
|
command: string;
|
|
@@ -16,10 +17,6 @@ export interface BuildDiscoveryOptions {
|
|
|
16
17
|
scope?: 'changed' | 'all';
|
|
17
18
|
changedFiles?: string[];
|
|
18
19
|
}
|
|
19
|
-
/**
|
|
20
|
-
* Check if a command exists on PATH
|
|
21
|
-
* Uses 'where' on Windows, 'which' on Unix
|
|
22
|
-
*/
|
|
23
20
|
export declare function isCommandAvailable(command: string): boolean;
|
|
24
21
|
/**
|
|
25
22
|
* Discover build commands using language profiles (primary detection path)
|
|
@@ -30,6 +27,7 @@ export declare const _internals: {
|
|
|
30
27
|
discoverBuildCommands: typeof discoverBuildCommands;
|
|
31
28
|
clearToolchainCache: typeof clearToolchainCache;
|
|
32
29
|
getEcosystems: typeof getEcosystems;
|
|
30
|
+
spawnSyncImpl: typeof bunSpawnSync;
|
|
33
31
|
};
|
|
34
32
|
export declare function discoverBuildCommandsFromProfiles(workingDir: string): Promise<BuildDiscoveryResult>;
|
|
35
33
|
/**
|