opencode-swarm 6.84.6 → 6.85.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/dist/cli/index.js +10 -6
- package/dist/hooks/repo-graph-builder.d.ts +11 -3
- package/dist/index.js +88 -4
- package/dist/utils/gitignore-warning.d.ts +17 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -45227,13 +45227,17 @@ async function install() {
|
|
|
45227
45227
|
\uD83D\uDE80 Installation complete!`);
|
|
45228
45228
|
console.log(`
|
|
45229
45229
|
Next steps:`);
|
|
45230
|
-
console.log(
|
|
45231
|
-
console.log(
|
|
45232
|
-
console.log("3.
|
|
45230
|
+
console.log('1. Run "opencode" in your project directory');
|
|
45231
|
+
console.log("2. Select the Architect agent in the OpenCode agent/mode dropdown");
|
|
45232
|
+
console.log("3. Ask it anything \u2014 the Architect coordinates all other agents automatically");
|
|
45233
|
+
console.log("4. Run /swarm diagnose inside OpenCode to confirm the plugin loaded");
|
|
45234
|
+
console.log(" (also try: /swarm agents /swarm config)");
|
|
45233
45235
|
console.log(`
|
|
45234
|
-
\uD83D\
|
|
45235
|
-
console.log(
|
|
45236
|
-
console.log("
|
|
45236
|
+
\uD83D\uDCA1 Model configuration:`);
|
|
45237
|
+
console.log(` Global config: ${PLUGIN_CONFIG_PATH}`);
|
|
45238
|
+
console.log(" Project override: .opencode/opencode-swarm.json (create in your project root)");
|
|
45239
|
+
console.log(" On first OpenCode startup, .swarm/config.example.json will be written to your project root");
|
|
45240
|
+
console.log(" \u2014 use it as a reference for customizing model assignments.");
|
|
45237
45241
|
return 0;
|
|
45238
45242
|
}
|
|
45239
45243
|
async function uninstall() {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* Write-trigger hook that incrementally updates the graph when write tools are called.
|
|
6
6
|
* Wrapped in try/catch — failures are logged but never block plugin initialization.
|
|
7
7
|
*/
|
|
8
|
+
import { type RepoGraph } from '../tools/repo-graph';
|
|
8
9
|
export interface RepoGraphBuilderHook {
|
|
9
10
|
init(): Promise<void>;
|
|
10
11
|
toolAfter(input: {
|
|
@@ -17,8 +18,15 @@ export interface RepoGraphBuilderHook {
|
|
|
17
18
|
}): Promise<void>;
|
|
18
19
|
}
|
|
19
20
|
export interface RepoGraphDeps {
|
|
20
|
-
buildWorkspaceGraph: (workspace: string, options?:
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
buildWorkspaceGraph: (workspace: string, options?: {
|
|
22
|
+
maxFileSizeBytes?: number;
|
|
23
|
+
maxFiles?: number;
|
|
24
|
+
}) => RepoGraph;
|
|
25
|
+
saveGraph: (workspace: string, graph: RepoGraph, options?: {
|
|
26
|
+
createAtomic?: boolean;
|
|
27
|
+
}) => Promise<void>;
|
|
28
|
+
updateGraphForFiles: (workspace: string, files: string[], options?: {
|
|
29
|
+
forceRebuild?: boolean;
|
|
30
|
+
}) => Promise<RepoGraph>;
|
|
23
31
|
}
|
|
24
32
|
export declare function createRepoGraphBuilderHook(workspaceRoot: string, deps?: Partial<RepoGraphDeps>): RepoGraphBuilderHook;
|
package/dist/index.js
CHANGED
|
@@ -23112,11 +23112,11 @@ function dcExtractPowerShellTargets(segment) {
|
|
|
23112
23112
|
function redactShellCommand(cmd) {
|
|
23113
23113
|
if (typeof cmd !== "string")
|
|
23114
23114
|
return "";
|
|
23115
|
-
let out2 = cmd.replace(/\b([A-Z_]*(?:TOKEN|SECRET|PASSWORD|PASSWD|API[_]?KEY|APIKEY|AUTH|CREDENTIAL|PRIVATE[_]?KEY|ACCESS[_]?KEY)[A-Z_0-9]*)\s*=\s*(\S+)/gi, "$1=[REDACTED]");
|
|
23115
|
+
let out2 = cmd.replace(/\b([A-Z_]*(?:TOKEN|SECRET|PASSWORD|PASSWD|API[_]?KEY|APIKEY|AUTH|CREDENTIAL|PRIVATE[_]?KEY|ACCESS[_]?KEY|_KEY)[A-Z_0-9]*)\s*=\s*(\S+)/gi, "$1=[REDACTED]");
|
|
23116
23116
|
out2 = out2.replace(/--([a-zA-Z-]*(?:token|secret|password|passwd|api[_-]?key|apikey|auth|credential|private[_-]?key|access[_-]?key)[a-zA-Z-]*)=(\S+)/gi, "--$1=[REDACTED]");
|
|
23117
23117
|
out2 = out2.replace(/(--[a-zA-Z-]*(?:token|secret|password|passwd|api[_-]?key|apikey|auth|credential|private[_-]?key|access[_-]?key)[a-zA-Z-]*)(\s+)(?!--)(\S+)/gi, "$1$2[REDACTED]");
|
|
23118
23118
|
out2 = out2.replace(/\b(Bearer|Basic)\s+[A-Za-z0-9+/=._-]{4,}/gi, "$1 [REDACTED]");
|
|
23119
|
-
out2 = out2.replace(/(-H\s+['"]?(?:Authorization|X-API-Key|X-Auth-Token):\s*)([^'">\s][^'">\n]*)(['"]?)/gi, "$1[REDACTED]$3");
|
|
23119
|
+
out2 = out2.replace(/(-H\s+['"]?(?:Authorization|X-API-Key|X-Auth-Token|[A-Za-z][A-Za-z-]*-(?:key|token|secret|auth|credential)):\s*)([^'">\s][^'">\n]*)(['"]?)/gi, "$1[REDACTED]$3");
|
|
23120
23120
|
return out2;
|
|
23121
23121
|
}
|
|
23122
23122
|
function createGuardrailsHooks(directory, directoryOrConfig, config2, authorityConfig) {
|
|
@@ -62828,7 +62828,8 @@ var init_curator_drift = __esm(() => {
|
|
|
62828
62828
|
|
|
62829
62829
|
// src/index.ts
|
|
62830
62830
|
init_agents();
|
|
62831
|
-
import * as
|
|
62831
|
+
import * as fs88 from "fs";
|
|
62832
|
+
import * as path104 from "path";
|
|
62832
62833
|
|
|
62833
62834
|
// src/background/index.ts
|
|
62834
62835
|
init_event_bus();
|
|
@@ -88084,6 +88085,67 @@ init_write_retro();
|
|
|
88084
88085
|
// src/index.ts
|
|
88085
88086
|
init_utils();
|
|
88086
88087
|
|
|
88088
|
+
// src/utils/gitignore-warning.ts
|
|
88089
|
+
import * as fs87 from "fs";
|
|
88090
|
+
import * as path103 from "path";
|
|
88091
|
+
var _gitignoreWarningEmitted = false;
|
|
88092
|
+
function findGitRoot(startDir) {
|
|
88093
|
+
let current = startDir;
|
|
88094
|
+
while (true) {
|
|
88095
|
+
try {
|
|
88096
|
+
const gitPath = path103.join(current, ".git");
|
|
88097
|
+
const stat4 = fs87.statSync(gitPath);
|
|
88098
|
+
if (stat4.isDirectory()) {
|
|
88099
|
+
return current;
|
|
88100
|
+
}
|
|
88101
|
+
} catch {}
|
|
88102
|
+
const parent = path103.dirname(current);
|
|
88103
|
+
if (parent === current) {
|
|
88104
|
+
return null;
|
|
88105
|
+
}
|
|
88106
|
+
current = parent;
|
|
88107
|
+
}
|
|
88108
|
+
}
|
|
88109
|
+
function fileCoversSwarm(content) {
|
|
88110
|
+
for (const rawLine of content.split(`
|
|
88111
|
+
`)) {
|
|
88112
|
+
const line = rawLine.trim();
|
|
88113
|
+
if (line.startsWith("#") || line.length === 0)
|
|
88114
|
+
continue;
|
|
88115
|
+
if (line === ".swarm" || line === ".swarm/")
|
|
88116
|
+
return true;
|
|
88117
|
+
}
|
|
88118
|
+
return false;
|
|
88119
|
+
}
|
|
88120
|
+
function readFileSafe(filePath) {
|
|
88121
|
+
try {
|
|
88122
|
+
return fs87.readFileSync(filePath, "utf8");
|
|
88123
|
+
} catch {
|
|
88124
|
+
return null;
|
|
88125
|
+
}
|
|
88126
|
+
}
|
|
88127
|
+
function warnIfSwarmNotGitignored(directory) {
|
|
88128
|
+
if (_gitignoreWarningEmitted)
|
|
88129
|
+
return;
|
|
88130
|
+
try {
|
|
88131
|
+
const gitRoot = findGitRoot(directory);
|
|
88132
|
+
if (!gitRoot)
|
|
88133
|
+
return;
|
|
88134
|
+
const gitignoreContent = readFileSafe(path103.join(gitRoot, ".gitignore"));
|
|
88135
|
+
if (gitignoreContent !== null && fileCoversSwarm(gitignoreContent)) {
|
|
88136
|
+
_gitignoreWarningEmitted = true;
|
|
88137
|
+
return;
|
|
88138
|
+
}
|
|
88139
|
+
const excludeContent = readFileSafe(path103.join(gitRoot, ".git", "info", "exclude"));
|
|
88140
|
+
if (excludeContent !== null && fileCoversSwarm(excludeContent)) {
|
|
88141
|
+
_gitignoreWarningEmitted = true;
|
|
88142
|
+
return;
|
|
88143
|
+
}
|
|
88144
|
+
_gitignoreWarningEmitted = true;
|
|
88145
|
+
console.warn('[opencode-swarm] WARNING: .swarm/ is not in your .gitignore. Shell audit logs may contain API keys. Add ".swarm/" to your .gitignore to prevent accidental commits.');
|
|
88146
|
+
} catch {}
|
|
88147
|
+
}
|
|
88148
|
+
|
|
88087
88149
|
// src/utils/tool-output.ts
|
|
88088
88150
|
function truncateToolOutput(output, maxLines, toolName, tailLines = 10) {
|
|
88089
88151
|
if (!output) {
|
|
@@ -88117,6 +88179,26 @@ ${footerLines.join(`
|
|
|
88117
88179
|
|
|
88118
88180
|
// src/index.ts
|
|
88119
88181
|
var _heartbeatTimers = new Map;
|
|
88182
|
+
function writeSwarmConfigExampleIfNew(projectDirectory) {
|
|
88183
|
+
try {
|
|
88184
|
+
const swarmDir = path104.join(projectDirectory, ".swarm");
|
|
88185
|
+
const dest = path104.join(swarmDir, "config.example.json");
|
|
88186
|
+
if (fs88.existsSync(dest))
|
|
88187
|
+
return;
|
|
88188
|
+
const example = {
|
|
88189
|
+
agents: Object.fromEntries(Object.entries(DEFAULT_MODELS).filter(([name2]) => name2 !== "default").map(([name2, model]) => [
|
|
88190
|
+
name2,
|
|
88191
|
+
{
|
|
88192
|
+
model,
|
|
88193
|
+
fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
|
|
88194
|
+
}
|
|
88195
|
+
])),
|
|
88196
|
+
max_iterations: 5
|
|
88197
|
+
};
|
|
88198
|
+
fs88.writeFileSync(dest, `${JSON.stringify(example, null, 2)}
|
|
88199
|
+
`, "utf-8");
|
|
88200
|
+
} catch {}
|
|
88201
|
+
}
|
|
88120
88202
|
var OpenCodeSwarm = async (ctx) => {
|
|
88121
88203
|
const { config: config3, loadedFromFile } = loadPluginConfigWithMeta(ctx.directory);
|
|
88122
88204
|
if (config3.full_auto?.enabled === true) {
|
|
@@ -88130,6 +88212,8 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
88130
88212
|
swarmState.opencodeClient = ctx.client;
|
|
88131
88213
|
await loadSnapshot(ctx.directory);
|
|
88132
88214
|
initTelemetry(ctx.directory);
|
|
88215
|
+
writeSwarmConfigExampleIfNew(ctx.directory);
|
|
88216
|
+
warnIfSwarmNotGitignored(ctx.directory);
|
|
88133
88217
|
const repoGraphHook = createRepoGraphBuilderHook(ctx.directory);
|
|
88134
88218
|
repoGraphHook.init().catch(() => {});
|
|
88135
88219
|
const agents = getAgentConfigs(config3, ctx.directory);
|
|
@@ -88249,7 +88333,7 @@ var OpenCodeSwarm = async (ctx) => {
|
|
|
88249
88333
|
const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
|
|
88250
88334
|
preflightTriggerManager = new PTM(automationConfig);
|
|
88251
88335
|
const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
|
|
88252
|
-
const swarmDir =
|
|
88336
|
+
const swarmDir = path104.resolve(ctx.directory, ".swarm");
|
|
88253
88337
|
statusArtifact = new ASA(swarmDir);
|
|
88254
88338
|
statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
|
|
88255
88339
|
if (automationConfig.capabilities?.evidence_auto_summaries === true) {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module-level flag so the warning fires at most once per process.
|
|
3
|
+
* Exported for test reset purposes only — do not use in production code.
|
|
4
|
+
*/
|
|
5
|
+
export declare let _gitignoreWarningEmitted: boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Reset the deduplication flag. Exposed for test isolation only.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resetGitignoreWarningState(): void;
|
|
10
|
+
/**
|
|
11
|
+
* Checks whether `.swarm/` is covered by `.gitignore` or `.git/info/exclude`
|
|
12
|
+
* in the git repo rooted at or above `directory`. If not covered, emits a
|
|
13
|
+
* single `console.warn`. Fires at most once per process.
|
|
14
|
+
*
|
|
15
|
+
* Never throws — any file-system error silently skips the check.
|
|
16
|
+
*/
|
|
17
|
+
export declare function warnIfSwarmNotGitignored(directory: string): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.85.0",
|
|
4
4
|
"description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|