opencode-architect 0.2.4 → 0.4.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/README.md +78 -18
- package/agent-loader.ts +98 -0
- package/assets/agents/opencode-agent-designer.md +13 -47
- package/assets/agents/opencode-architect.md +60 -244
- package/assets/agents/opencode-command-crafter.md +9 -27
- package/assets/agents/opencode-extension-auditor.md +25 -36
- package/assets/agents/opencode-mcp-integrator.md +13 -17
- package/assets/agents/opencode-packager.md +31 -203
- package/assets/agents/opencode-plugin-engineer.md +16 -29
- package/assets/agents/opencode-publisher.md +27 -206
- package/assets/agents/opencode-skill-creator.md +15 -35
- package/assets/agents/opencode-tool-builder.md +13 -17
- package/assets/references/agents.md +68 -0
- package/assets/references/commands.md +49 -0
- package/assets/references/config.md +50 -0
- package/assets/references/mcp-servers.md +55 -0
- package/assets/references/opencode-architect-oneshots.md +19 -58
- package/assets/references/plugins.md +76 -0
- package/assets/references/prompt-engineering.md +46 -0
- package/assets/references/skills.md +55 -0
- package/assets/references/tools.md +49 -0
- package/assets/templates/skill-structure.template.md +4 -4
- package/cli.ts +120 -0
- package/index.ts +4 -103
- package/installer.ts +319 -0
- package/package.json +30 -8
- package/assets/templates/package-analysis.template.md +0 -60
- package/commands/sync-docs.ts +0 -9
- package/scripts/fetch-opencode-docs.ts +0 -193
- package/scripts/logger.ts +0 -20
- package/tools/sync-docs.ts +0 -24
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
# Package Analysis Template
|
|
2
|
-
|
|
3
|
-
Use this template to document extension analysis before packaging.
|
|
4
|
-
|
|
5
|
-
## Source Information
|
|
6
|
-
|
|
7
|
-
- **Source Path**: [path to .opencode/ or existing package]
|
|
8
|
-
- **Source Type**: [project-local | existing-package]
|
|
9
|
-
- **Target Package Name**: opencode-[name]
|
|
10
|
-
|
|
11
|
-
## Extension Inventory
|
|
12
|
-
|
|
13
|
-
### Skills
|
|
14
|
-
| Name | Description | Dependencies | Issues |
|
|
15
|
-
| ---- | ----------- | ------------ | ------ |
|
|
16
|
-
| | | | |
|
|
17
|
-
|
|
18
|
-
### Commands
|
|
19
|
-
| Name | Description | Template Vars | Issues |
|
|
20
|
-
| ---- | ----------- | ------------- | ------ |
|
|
21
|
-
| | | | |
|
|
22
|
-
|
|
23
|
-
### Agents
|
|
24
|
-
| Name | Description | Mode | Issues |
|
|
25
|
-
| ---- | ----------- | ---- | ------ |
|
|
26
|
-
| | | | |
|
|
27
|
-
|
|
28
|
-
### Plugins
|
|
29
|
-
| File | Hooks Used | Merge Strategy | Issues |
|
|
30
|
-
| ---- | ---------- | -------------- | ------ |
|
|
31
|
-
| | | | |
|
|
32
|
-
|
|
33
|
-
### Tools
|
|
34
|
-
| File | Tool Name | Merge Strategy | Issues |
|
|
35
|
-
| ---- | --------- | -------------- | ------ |
|
|
36
|
-
| | | | |
|
|
37
|
-
|
|
38
|
-
## Dependencies
|
|
39
|
-
|
|
40
|
-
From `.opencode/package.json`:
|
|
41
|
-
- [list dependencies]
|
|
42
|
-
|
|
43
|
-
## Packaging Assessment
|
|
44
|
-
|
|
45
|
-
- **Complexity**: [simple | medium | complex]
|
|
46
|
-
- **Requires Guidance**: [yes | no]
|
|
47
|
-
- **Guidance Needed For**: [plugins | tools | both | none]
|
|
48
|
-
|
|
49
|
-
## Recommendations
|
|
50
|
-
|
|
51
|
-
1. [recommendation 1]
|
|
52
|
-
2. [recommendation 2]
|
|
53
|
-
|
|
54
|
-
## Merge Decisions (if applicable)
|
|
55
|
-
|
|
56
|
-
### Plugin Merge
|
|
57
|
-
- [decision and rationale]
|
|
58
|
-
|
|
59
|
-
### Tool Merge
|
|
60
|
-
- [decision and rationale]
|
package/commands/sync-docs.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { Config } from "@opencode-ai/sdk";
|
|
2
|
-
|
|
3
|
-
export const command: NonNullable<Config["command"]>[string] = {
|
|
4
|
-
description: "Sync OpenCode docs into ~/.cache/opencode/opencode-architect/docs",
|
|
5
|
-
template:
|
|
6
|
-
"Use the sync-docs tool to fetch the latest OpenCode documentation into `~/.cache/opencode/opencode-architect/docs`.",
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export default command;
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
-
import os from "node:os";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
|
|
5
|
-
import type { Logger } from "./logger";
|
|
6
|
-
import { ConsoleLogger } from "./logger";
|
|
7
|
-
|
|
8
|
-
interface ExternalDoc {
|
|
9
|
-
url: string;
|
|
10
|
-
filename: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export class OpenCodeDocsFetcher {
|
|
14
|
-
private readonly sitemapUrl: string;
|
|
15
|
-
private readonly docsDir: string;
|
|
16
|
-
private readonly externalDocs: ExternalDoc[];
|
|
17
|
-
private readonly logger: Logger;
|
|
18
|
-
|
|
19
|
-
public constructor(logger: Logger | null = null) {
|
|
20
|
-
this.sitemapUrl = "https://opencode.ai/sitemap.xml";
|
|
21
|
-
this.docsDir = path.join(
|
|
22
|
-
os.homedir(),
|
|
23
|
-
".cache",
|
|
24
|
-
"opencode",
|
|
25
|
-
"opencode-architect",
|
|
26
|
-
"docs",
|
|
27
|
-
);
|
|
28
|
-
this.logger = logger ?? new ConsoleLogger();
|
|
29
|
-
this.externalDocs = [
|
|
30
|
-
{
|
|
31
|
-
url: "https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices.md",
|
|
32
|
-
filename: "claude-skill-best-practices.md",
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
url: "https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-4-best-practices.md",
|
|
36
|
-
filename: "claude-4-best-practices.md",
|
|
37
|
-
},
|
|
38
|
-
];
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
public async run(): Promise<void> {
|
|
42
|
-
try {
|
|
43
|
-
await this.ensureDocsDir();
|
|
44
|
-
const sitemap = await this.fetchText(this.sitemapUrl);
|
|
45
|
-
const docUrls = this.extractDocUrls(sitemap);
|
|
46
|
-
const markdownUrls = this.buildMarkdownUrls(docUrls);
|
|
47
|
-
await this.downloadDocs(markdownUrls);
|
|
48
|
-
await this.downloadExternalDocs();
|
|
49
|
-
} catch (error) {
|
|
50
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
51
|
-
this.logger.error(`Failed to fetch OpenCode docs: ${message}`);
|
|
52
|
-
process.exitCode = 1;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
private async ensureDocsDir(): Promise<void> {
|
|
57
|
-
await mkdir(this.docsDir, { recursive: true });
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
private async fetchText(url: string): Promise<string> {
|
|
61
|
-
const response = await fetch(url, {
|
|
62
|
-
headers: {
|
|
63
|
-
"User-Agent": "opencode-docs-fetcher",
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
if (!response.ok) {
|
|
67
|
-
throw new Error(`Request failed (${response.status}) for ${url}`);
|
|
68
|
-
}
|
|
69
|
-
return await response.text();
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
private extractDocUrls(sitemap: string): string[] {
|
|
73
|
-
const urls: string[] = [];
|
|
74
|
-
const regex = /<loc>([^<]+)<\/loc>/g;
|
|
75
|
-
let match: RegExpExecArray | null = regex.exec(sitemap);
|
|
76
|
-
while (match) {
|
|
77
|
-
const url = match[1];
|
|
78
|
-
if (url !== undefined) {
|
|
79
|
-
try {
|
|
80
|
-
const parsed = new URL(url);
|
|
81
|
-
if (parsed.pathname.startsWith("/docs/")) {
|
|
82
|
-
urls.push(url);
|
|
83
|
-
}
|
|
84
|
-
} catch {
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
match = regex.exec(sitemap);
|
|
89
|
-
}
|
|
90
|
-
return Array.from(new Set(urls));
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
private buildMarkdownUrls(urls: string[]): string[] {
|
|
94
|
-
const markdownUrls: string[] = [];
|
|
95
|
-
for (const url of urls) {
|
|
96
|
-
const parsed = new URL(url);
|
|
97
|
-
if (!parsed.pathname.startsWith("/docs/")) {
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
const normalizedPath = this.normalizeDocPath(parsed.pathname);
|
|
101
|
-
if (normalizedPath === "/docs") {
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
const markdownUrl = `${parsed.origin}${normalizedPath}.md`;
|
|
105
|
-
markdownUrls.push(markdownUrl);
|
|
106
|
-
}
|
|
107
|
-
return Array.from(new Set(markdownUrls));
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
private normalizeDocPath(pathname: string): string {
|
|
111
|
-
if (pathname.endsWith("/")) {
|
|
112
|
-
return pathname.slice(0, -1);
|
|
113
|
-
}
|
|
114
|
-
return pathname;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
private async downloadDocs(urls: string[]): Promise<void> {
|
|
118
|
-
let successCount = 0;
|
|
119
|
-
let failureCount = 0;
|
|
120
|
-
for (const url of urls) {
|
|
121
|
-
try {
|
|
122
|
-
const content = await this.fetchText(url);
|
|
123
|
-
const filename = this.buildFilename(url);
|
|
124
|
-
const filePath = path.join(this.docsDir, filename);
|
|
125
|
-
await writeFile(filePath, content);
|
|
126
|
-
successCount += 1;
|
|
127
|
-
} catch (error) {
|
|
128
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
129
|
-
this.logger.error(`Failed to fetch ${url}: ${message}`);
|
|
130
|
-
failureCount += 1;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
this.logger.info(
|
|
135
|
-
`OpenCode docs fetch complete. Success: ${successCount}, Failed: ${failureCount}.`,
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
private async downloadExternalDocs(): Promise<void> {
|
|
140
|
-
let successCount = 0;
|
|
141
|
-
let failureCount = 0;
|
|
142
|
-
for (const doc of this.externalDocs) {
|
|
143
|
-
try {
|
|
144
|
-
const content = await this.fetchText(doc.url);
|
|
145
|
-
const filePath = path.join(this.docsDir, doc.filename);
|
|
146
|
-
await writeFile(filePath, content);
|
|
147
|
-
successCount += 1;
|
|
148
|
-
} catch (error) {
|
|
149
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
150
|
-
this.logger.error(`Failed to fetch ${doc.url}: ${message}`);
|
|
151
|
-
failureCount += 1;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
this.logger.info(
|
|
156
|
-
`External docs fetch complete. Success: ${successCount}, Failed: ${failureCount}.`,
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
private buildFilename(url: string): string {
|
|
161
|
-
const parsed = new URL(url);
|
|
162
|
-
const pathname = parsed.pathname;
|
|
163
|
-
if (pathname === "/docs.md" || pathname === "/docs/.md") {
|
|
164
|
-
return "index.md";
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
let relative = pathname;
|
|
168
|
-
if (relative.startsWith("/docs/")) {
|
|
169
|
-
relative = relative.slice("/docs/".length);
|
|
170
|
-
} else if (relative.startsWith("/docs")) {
|
|
171
|
-
relative = relative.slice("/docs".length);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (relative.startsWith("/")) {
|
|
175
|
-
relative = relative.slice(1);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (relative.length === 0) {
|
|
179
|
-
return "index.md";
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const normalized = relative.replace(/\//g, "-");
|
|
183
|
-
if (normalized.endsWith(".md")) {
|
|
184
|
-
return normalized;
|
|
185
|
-
}
|
|
186
|
-
return `${normalized}.md`;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (import.meta.main) {
|
|
192
|
-
void new OpenCodeDocsFetcher().run();
|
|
193
|
-
}
|
package/scripts/logger.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export interface Logger {
|
|
2
|
-
info(message: string): void;
|
|
3
|
-
error(message: string): void;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export class ConsoleLogger implements Logger {
|
|
7
|
-
public info(message: string): void {
|
|
8
|
-
console.log(message);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
public error(message: string): void {
|
|
12
|
-
console.error(message);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export class SilentLogger implements Logger {
|
|
17
|
-
public info(_message: string): void {}
|
|
18
|
-
|
|
19
|
-
public error(_message: string): void {}
|
|
20
|
-
}
|
package/tools/sync-docs.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { tool } from "@opencode-ai/plugin";
|
|
2
|
-
|
|
3
|
-
import { OpenCodeDocsFetcher } from "../scripts/fetch-opencode-docs";
|
|
4
|
-
|
|
5
|
-
type ToolDefinition = ReturnType<typeof tool>;
|
|
6
|
-
|
|
7
|
-
function createSyncDocsTool(): ToolDefinition {
|
|
8
|
-
return tool({
|
|
9
|
-
description: "Sync OpenCode documentation by fetching the latest docs from opencode.ai",
|
|
10
|
-
args: {},
|
|
11
|
-
async execute(_args, _context) {
|
|
12
|
-
try {
|
|
13
|
-
const fetcher = new OpenCodeDocsFetcher();
|
|
14
|
-
await fetcher.run();
|
|
15
|
-
return "Successfully synced OpenCode documentation.";
|
|
16
|
-
} catch (error) {
|
|
17
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
18
|
-
return `Failed to sync docs: ${message}`;
|
|
19
|
-
}
|
|
20
|
-
},
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export { createSyncDocsTool };
|