opencodekit 0.14.6 → 0.15.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.
Files changed (95) hide show
  1. package/README.md +2 -2
  2. package/dist/index.js +100 -58
  3. package/dist/template/.opencode/.env.example +1 -0
  4. package/dist/template/.opencode/AGENTS.md +13 -24
  5. package/dist/template/.opencode/README.md +8 -119
  6. package/dist/template/.opencode/agent/explore.md +2 -3
  7. package/dist/template/.opencode/agent/general.md +56 -0
  8. package/dist/template/.opencode/agent/plan.md +54 -0
  9. package/dist/template/.opencode/agent/scout.md +15 -5
  10. package/dist/template/.opencode/command/analyze-project.md +2 -2
  11. package/dist/template/.opencode/command/brainstorm.md +1 -1
  12. package/dist/template/.opencode/command/design-audit.md +4 -5
  13. package/dist/template/.opencode/command/design.md +4 -13
  14. package/dist/template/.opencode/command/generate-pattern.md +2 -9
  15. package/dist/template/.opencode/command/implement.md +4 -4
  16. package/dist/template/.opencode/command/init.md +1 -1
  17. package/dist/template/.opencode/command/new-feature.md +2 -3
  18. package/dist/template/.opencode/command/plan.md +1 -1
  19. package/dist/template/.opencode/command/pr.md +0 -1
  20. package/dist/template/.opencode/command/research.md +20 -6
  21. package/dist/template/.opencode/command/restore-image.md +1 -9
  22. package/dist/template/.opencode/command/revert-feature.md +1 -1
  23. package/dist/template/.opencode/command/review-codebase.md +4 -4
  24. package/dist/template/.opencode/command/status.md +1 -2
  25. package/dist/template/.opencode/command/summarize.md +1 -2
  26. package/dist/template/.opencode/command/triage.md +4 -32
  27. package/dist/template/.opencode/dcp.jsonc +68 -68
  28. package/dist/template/.opencode/memory/_templates/README.md +35 -0
  29. package/dist/template/.opencode/memory/_templates/project/architecture.md +60 -0
  30. package/dist/template/.opencode/memory/_templates/project/commands.md +72 -0
  31. package/dist/template/.opencode/memory/_templates/project/conventions.md +68 -0
  32. package/dist/template/.opencode/memory/_templates/project/gotchas.md +41 -0
  33. package/dist/template/.opencode/memory/beads-workflow.md +30 -29
  34. package/dist/template/.opencode/memory/project/architecture.md +31 -50
  35. package/dist/template/.opencode/memory/project/commands.md +41 -22
  36. package/dist/template/.opencode/memory/project/conventions.md +39 -177
  37. package/dist/template/.opencode/memory/project/gotchas.md +21 -177
  38. package/dist/template/.opencode/memory/user.example.md +5 -0
  39. package/dist/template/.opencode/opencode.json +644 -579
  40. package/dist/template/.opencode/package.json +18 -21
  41. package/dist/template/.opencode/plugin/compaction.ts +79 -85
  42. package/dist/template/.opencode/plugin/env-ctx.ts +19 -19
  43. package/dist/template/.opencode/plugin/lib/notify.ts +41 -45
  44. package/dist/template/.opencode/plugin/lsp.ts +197 -200
  45. package/dist/template/.opencode/plugin/memory.ts +14 -112
  46. package/dist/template/.opencode/plugin/package.json +5 -5
  47. package/dist/template/.opencode/plugin/sessions.ts +1 -1
  48. package/dist/template/.opencode/plugin/skill-mcp.ts +486 -521
  49. package/dist/template/.opencode/plugin/truncator.ts +47 -50
  50. package/dist/template/.opencode/plugin/tsconfig.json +14 -14
  51. package/dist/template/.opencode/skill/chrome-devtools/mcp.json +17 -17
  52. package/dist/template/.opencode/skill/condition-based-waiting/SKILL.md +17 -12
  53. package/dist/template/.opencode/skill/condition-based-waiting/example.ts +63 -69
  54. package/dist/template/.opencode/skill/defense-in-depth/SKILL.md +14 -8
  55. package/dist/template/.opencode/skill/dispatching-parallel-agents/SKILL.md +14 -3
  56. package/dist/template/.opencode/skill/playwright/mcp.json +14 -14
  57. package/dist/template/.opencode/skill/receiving-code-review/SKILL.md +21 -8
  58. package/dist/template/.opencode/skill/requesting-code-review/review.md +14 -0
  59. package/dist/template/.opencode/skill/root-cause-tracing/SKILL.md +18 -4
  60. package/dist/template/.opencode/skill/source-code-research/SKILL.md +9 -7
  61. package/dist/template/.opencode/skill/test-driven-development/SKILL.md +49 -32
  62. package/dist/template/.opencode/skill/testing-anti-patterns/SKILL.md +40 -22
  63. package/dist/template/.opencode/skill/testing-skills-with-subagents/SKILL.md +46 -26
  64. package/dist/template/.opencode/skill/tool-priority/SKILL.md +117 -44
  65. package/dist/template/.opencode/skill/v0/SKILL.md +1 -7
  66. package/dist/template/.opencode/skill/verification-before-completion/SKILL.md +27 -19
  67. package/dist/template/.opencode/skill/writing-skills/anthropic-best-practices.md +171 -148
  68. package/dist/template/.opencode/skill/writing-skills/persuasion-principles.md +39 -6
  69. package/dist/template/.opencode/tool/memory-read.ts +44 -56
  70. package/dist/template/.opencode/tool/memory-search.ts +8 -291
  71. package/dist/template/.opencode/tool/memory-update.ts +47 -51
  72. package/dist/template/.opencode/tool/observation.ts +6 -180
  73. package/dist/template/.opencode/tsconfig.json +19 -19
  74. package/package.json +19 -15
  75. package/dist/template/.opencode/.background-tasks.json +0 -114
  76. package/dist/template/.opencode/.ralph-state.json +0 -12
  77. package/dist/template/.opencode/agent/build.md +0 -327
  78. package/dist/template/.opencode/agent/ninja.md +0 -351
  79. package/dist/template/.opencode/agent/planner.md +0 -281
  80. package/dist/template/.opencode/agent/rush.md +0 -223
  81. package/dist/template/.opencode/memory/handoffs/README.md +0 -83
  82. package/dist/template/.opencode/memory/observations/.gitkeep +0 -0
  83. package/dist/template/.opencode/memory/observations/2026-01-09-pattern-ampcode-mcp-json-includetools-pattern.md +0 -42
  84. package/dist/template/.opencode/memory/vector_db/memories.lance/_transactions/0-0d25ba80-ba3b-4209-9046-b45d6093b4da.txn +0 -0
  85. package/dist/template/.opencode/memory/vector_db/memories.lance/_versions/1.manifest +0 -0
  86. package/dist/template/.opencode/memory/vector_db/memories.lance/data/1111100101010101011010004a9ef34df6b29f36a9a53a2892.lance +0 -0
  87. package/dist/template/.opencode/tool/ast-grep.ts +0 -245
  88. package/dist/template/.opencode/tool/background.ts +0 -509
  89. package/dist/template/.opencode/tool/bd-inbox.ts +0 -110
  90. package/dist/template/.opencode/tool/bd-msg.ts +0 -62
  91. package/dist/template/.opencode/tool/bd-release.ts +0 -71
  92. package/dist/template/.opencode/tool/bd-reserve.ts +0 -121
  93. package/dist/template/.opencode/tool/memory-embed.ts +0 -183
  94. package/dist/template/.opencode/tool/memory-index.ts +0 -769
  95. package/dist/template/.opencode/tool/repo-map.ts +0 -451
@@ -1,71 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
3
- import { tool } from "@opencode-ai/plugin";
4
-
5
- const RESERVATIONS_DIR = ".reservations";
6
-
7
- function lockDir(filePath: string): string {
8
- const safe = filePath.replace(/[/\\]/g, "_").replace(/\.\./g, "_");
9
- return path.join(RESERVATIONS_DIR, `${safe}.lock`);
10
- }
11
-
12
- export default tool({
13
- description:
14
- "Release file locks. If no paths specified, lists all active locks.",
15
- args: {
16
- paths: tool.schema
17
- .array(tool.schema.string())
18
- .optional()
19
- .describe("File paths to unlock (empty = list locks)"),
20
- },
21
- execute: async (args) => {
22
- const cwd = process.cwd();
23
- const reservationsPath = path.join(cwd, RESERVATIONS_DIR);
24
-
25
- // If no paths, list locks
26
- if (!args.paths?.length) {
27
- try {
28
- const entries = await fs.readdir(reservationsPath);
29
- const locks = [];
30
- const now = Date.now();
31
-
32
- for (const entry of entries) {
33
- if (entry.endsWith(".lock")) {
34
- const metaPath = path.join(reservationsPath, entry, "meta.json");
35
- try {
36
- const content = await fs.readFile(metaPath, "utf-8");
37
- const lock = JSON.parse(content);
38
- if (lock.expires > now) {
39
- locks.push({
40
- path: lock.path,
41
- agent: lock.agent,
42
- expires: new Date(lock.expires).toISOString(),
43
- });
44
- }
45
- } catch {
46
- // Skip invalid locks
47
- }
48
- }
49
- }
50
-
51
- return JSON.stringify({ locks, count: locks.length });
52
- } catch {
53
- return JSON.stringify({ locks: [], count: 0 });
54
- }
55
- }
56
-
57
- // Release specified paths
58
- const released: string[] = [];
59
- for (const filePath of args.paths) {
60
- const lockPath = path.join(cwd, lockDir(filePath));
61
- try {
62
- await fs.rm(lockPath, { recursive: true });
63
- released.push(filePath);
64
- } catch {
65
- // Already released or never locked
66
- }
67
- }
68
-
69
- return JSON.stringify({ released });
70
- },
71
- });
@@ -1,121 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
3
- import { tool } from "@opencode-ai/plugin";
4
-
5
- const RESERVATIONS_DIR = ".reservations";
6
-
7
- interface LockData {
8
- path: string;
9
- agent: string;
10
- reason?: string;
11
- created: number;
12
- expires: number;
13
- }
14
-
15
- function lockDir(filePath: string): string {
16
- const safe = filePath.replace(/[/\\]/g, "_").replace(/\.\./g, "_");
17
- return path.join(RESERVATIONS_DIR, `${safe}.lock`);
18
- }
19
-
20
- export default tool({
21
- description:
22
- "Lock files for editing to prevent conflicts between agents. Uses atomic mkdir-based locking.",
23
- args: {
24
- paths: tool.schema
25
- .array(tool.schema.string())
26
- .describe("File paths to lock"),
27
- reason: tool.schema
28
- .string()
29
- .optional()
30
- .describe("Why reserving these files"),
31
- ttl: tool.schema
32
- .number()
33
- .optional()
34
- .default(600)
35
- .describe("Lock TTL in seconds (default 600 = 10 min)"),
36
- },
37
- execute: async (args, context) => {
38
- if (!args.paths?.length) {
39
- return JSON.stringify({ error: "paths required" });
40
- }
41
-
42
- const cwd = process.cwd();
43
- const agentId = context?.agent || `agent-${process.pid}`;
44
- const ttlSeconds = args.ttl || 600;
45
- const now = Date.now();
46
- const expires = now + ttlSeconds * 1000;
47
-
48
- // Ensure reservations dir exists
49
- await fs.mkdir(path.join(cwd, RESERVATIONS_DIR), { recursive: true });
50
-
51
- const granted: string[] = [];
52
- const conflicts: { path: string; holder?: string }[] = [];
53
-
54
- for (const filePath of args.paths) {
55
- const lockPath = path.join(cwd, lockDir(filePath));
56
- const metaPath = path.join(lockPath, "meta.json");
57
-
58
- try {
59
- // Atomic: mkdir fails if dir exists
60
- await fs.mkdir(lockPath, { recursive: false });
61
-
62
- // Lock acquired - write metadata
63
- const lockData: LockData = {
64
- path: filePath,
65
- agent: agentId,
66
- reason: args.reason,
67
- created: now,
68
- expires,
69
- };
70
- await fs.writeFile(metaPath, JSON.stringify(lockData), "utf-8");
71
- granted.push(filePath);
72
- } catch (e) {
73
- const err = e as NodeJS.ErrnoException;
74
- if (err.code === "EEXIST") {
75
- // Lock exists - check if expired or ours
76
- try {
77
- const content = await fs.readFile(metaPath, "utf-8");
78
- const lock: LockData = JSON.parse(content);
79
-
80
- if (lock.expires < now) {
81
- // Expired - remove and retry
82
- await fs.rm(lockPath, { recursive: true });
83
- // Retry acquisition
84
- try {
85
- await fs.mkdir(lockPath, { recursive: false });
86
- const lockData: LockData = {
87
- path: filePath,
88
- agent: agentId,
89
- reason: args.reason,
90
- created: now,
91
- expires,
92
- };
93
- await fs.writeFile(metaPath, JSON.stringify(lockData), "utf-8");
94
- granted.push(filePath);
95
- } catch {
96
- conflicts.push({ path: filePath });
97
- }
98
- } else if (lock.agent === agentId) {
99
- // We already hold it - refresh
100
- lock.expires = expires;
101
- await fs.writeFile(metaPath, JSON.stringify(lock), "utf-8");
102
- granted.push(filePath);
103
- } else {
104
- conflicts.push({ path: filePath, holder: lock.agent });
105
- }
106
- } catch {
107
- // Corrupted lock - remove and retry
108
- await fs.rm(lockPath, { recursive: true, force: true });
109
- conflicts.push({ path: filePath });
110
- }
111
- } else {
112
- conflicts.push({ path: filePath });
113
- }
114
- }
115
- }
116
-
117
- const response: Record<string, unknown> = { granted };
118
- if (conflicts.length) response.conflicts = conflicts;
119
- return JSON.stringify(response);
120
- },
121
- });
@@ -1,183 +0,0 @@
1
- import { tool } from "@opencode-ai/plugin";
2
-
3
- // Configuration - Qwen3-Embedding-0.6B
4
- // Better for code, multilingual (100+ langs), instruction-aware
5
- // See: https://ollama.com/library/qwen3-embedding
6
- const OLLAMA_MODEL = "qwen3-embedding:0.6b";
7
- const OLLAMA_DIMENSIONS = 1024;
8
- const OLLAMA_BASE_URL = process.env.OLLAMA_HOST || "http://127.0.0.1:11434";
9
-
10
- interface EmbeddingResult {
11
- text: string;
12
- embedding: number[];
13
- model: string;
14
- dimensions: number;
15
- }
16
-
17
- interface BatchEmbeddingResult {
18
- results: EmbeddingResult[];
19
- failed: { text: string; error: string }[];
20
- model: string;
21
- }
22
-
23
- async function checkOllamaRunning(): Promise<boolean> {
24
- try {
25
- const response = await fetch(`${OLLAMA_BASE_URL}/api/version`, {
26
- method: "GET",
27
- signal: AbortSignal.timeout(3000),
28
- });
29
- return response.ok;
30
- } catch {
31
- return false;
32
- }
33
- }
34
-
35
- async function ensureModelAvailable(): Promise<{
36
- ok: boolean;
37
- error?: string;
38
- }> {
39
- try {
40
- const listResponse = await fetch(`${OLLAMA_BASE_URL}/api/tags`, {
41
- method: "GET",
42
- signal: AbortSignal.timeout(5000),
43
- });
44
-
45
- if (!listResponse.ok) {
46
- return { ok: false, error: "Failed to list models" };
47
- }
48
-
49
- const data = (await listResponse.json()) as {
50
- models?: { name: string }[];
51
- };
52
- const models = data.models || [];
53
- const modelExists = models.some(
54
- (m) => m.name === OLLAMA_MODEL || m.name === `${OLLAMA_MODEL}:latest`,
55
- );
56
-
57
- if (modelExists) {
58
- return { ok: true };
59
- }
60
-
61
- return {
62
- ok: false,
63
- error: `Model '${OLLAMA_MODEL}' not found. Run: ollama pull ${OLLAMA_MODEL}`,
64
- };
65
- } catch (err) {
66
- const message = err instanceof Error ? err.message : String(err);
67
- return { ok: false, error: `Failed to check models: ${message}` };
68
- }
69
- }
70
-
71
- async function embedWithOllama(
72
- texts: string[],
73
- ): Promise<{ embeddings: number[][]; error?: string }> {
74
- try {
75
- const embeddings: number[][] = [];
76
-
77
- for (const text of texts) {
78
- const response = await fetch(`${OLLAMA_BASE_URL}/api/embeddings`, {
79
- method: "POST",
80
- headers: { "Content-Type": "application/json" },
81
- body: JSON.stringify({
82
- model: OLLAMA_MODEL,
83
- prompt: text,
84
- }),
85
- signal: AbortSignal.timeout(30000),
86
- });
87
-
88
- if (!response.ok) {
89
- const errorText = await response.text();
90
- return {
91
- embeddings: [],
92
- error: `Ollama API error (${response.status}): ${errorText}`,
93
- };
94
- }
95
-
96
- const data = (await response.json()) as { embedding?: number[] };
97
- if (!data.embedding) {
98
- return { embeddings: [], error: "No embedding in response" };
99
- }
100
-
101
- embeddings.push(data.embedding);
102
- }
103
-
104
- return { embeddings };
105
- } catch (err) {
106
- const message = err instanceof Error ? err.message : String(err);
107
-
108
- if (message.includes("ECONNREFUSED") || message.includes("fetch failed")) {
109
- return {
110
- embeddings: [],
111
- error: "Cannot connect to Ollama. See .opencode/README.md for setup.",
112
- };
113
- }
114
-
115
- return { embeddings: [], error: `Ollama error: ${message}` };
116
- }
117
- }
118
-
119
- export default tool({
120
- description: `Generate embeddings using Ollama (${OLLAMA_MODEL}). Requires Ollama running locally.`,
121
- args: {
122
- text: tool.schema
123
- .union([tool.schema.string(), tool.schema.array(tool.schema.string())])
124
- .describe("Text or array of texts to embed"),
125
- },
126
- execute: async (args: { text: string | string[] }) => {
127
- const texts = Array.isArray(args.text) ? args.text : [args.text];
128
-
129
- if (texts.length === 0) {
130
- return "Error: No text provided";
131
- }
132
-
133
- const maxChars = 32000;
134
- const longTexts = texts.filter((t) => t.length > maxChars);
135
- if (longTexts.length > 0) {
136
- return `Error: ${longTexts.length} text(s) exceed ${maxChars} char limit`;
137
- }
138
-
139
- const ollamaRunning = await checkOllamaRunning();
140
- if (!ollamaRunning) {
141
- return "Error: Ollama not running. See .opencode/README.md for setup.";
142
- }
143
-
144
- const modelCheck = await ensureModelAvailable();
145
- if (!modelCheck.ok) {
146
- return `Error: ${modelCheck.error}. See .opencode/README.md for setup.`;
147
- }
148
-
149
- const result = await embedWithOllama(texts);
150
-
151
- if (result.error) {
152
- return `Error: ${result.error}`;
153
- }
154
-
155
- const response: BatchEmbeddingResult = {
156
- results: texts.map((text, i) => ({
157
- text: text.substring(0, 100) + (text.length > 100 ? "..." : ""),
158
- embedding: result.embeddings[i],
159
- model: OLLAMA_MODEL,
160
- dimensions: OLLAMA_DIMENSIONS,
161
- })),
162
- failed: [],
163
- model: OLLAMA_MODEL,
164
- };
165
-
166
- return JSON.stringify(response, null, 2);
167
- },
168
- });
169
-
170
- // Export for other tools (memory-index, observation)
171
- export async function generateEmbedding(
172
- text: string,
173
- ): Promise<{ embedding: number[]; model: string } | null> {
174
- const ollamaRunning = await checkOllamaRunning();
175
- if (!ollamaRunning) return null;
176
-
177
- const result = await embedWithOllama([text]);
178
- if (result.error || result.embeddings.length === 0) return null;
179
-
180
- return { embedding: result.embeddings[0], model: OLLAMA_MODEL };
181
- }
182
-
183
- export const EMBEDDING_DIMENSIONS = OLLAMA_DIMENSIONS;