@voxslopuli/openagentsy 0.0.0-stage → 0.2.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/LICENSE +674 -0
- package/README.md +21 -2
- package/dist/adapter-dependency.test.d.ts +2 -0
- package/dist/adapter-dependency.test.d.ts.map +1 -0
- package/dist/adapter-dependency.test.js +51 -0
- package/dist/adapter-dependency.test.js.map +1 -0
- package/dist/commands/approve.d.ts +63 -0
- package/dist/commands/approve.d.ts.map +1 -0
- package/dist/commands/approve.js +218 -0
- package/dist/commands/approve.js.map +1 -0
- package/dist/commands/approve.test.d.ts +2 -0
- package/dist/commands/approve.test.d.ts.map +1 -0
- package/dist/commands/approve.test.js +219 -0
- package/dist/commands/approve.test.js.map +1 -0
- package/dist/commands/audit.d.ts +74 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/audit.js +230 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/audit.test.d.ts +2 -0
- package/dist/commands/audit.test.d.ts.map +1 -0
- package/dist/commands/audit.test.js +194 -0
- package/dist/commands/audit.test.js.map +1 -0
- package/dist/commands/board.d.ts +33 -0
- package/dist/commands/board.d.ts.map +1 -0
- package/dist/commands/board.js +65 -0
- package/dist/commands/board.js.map +1 -0
- package/dist/commands/build.d.ts +17 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +145 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/conformance.d.ts +31 -0
- package/dist/commands/conformance.d.ts.map +1 -0
- package/dist/commands/conformance.js +57 -0
- package/dist/commands/conformance.js.map +1 -0
- package/dist/commands/conformance.test.d.ts +2 -0
- package/dist/commands/conformance.test.d.ts.map +1 -0
- package/dist/commands/conformance.test.js +74 -0
- package/dist/commands/conformance.test.js.map +1 -0
- package/dist/commands/doctor.d.ts +132 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +768 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/doctor.test.d.ts +2 -0
- package/dist/commands/doctor.test.d.ts.map +1 -0
- package/dist/commands/doctor.test.js +329 -0
- package/dist/commands/doctor.test.js.map +1 -0
- package/dist/commands/ledger.d.ts +109 -0
- package/dist/commands/ledger.d.ts.map +1 -0
- package/dist/commands/ledger.js +286 -0
- package/dist/commands/ledger.js.map +1 -0
- package/dist/commands/ledger.test.d.ts +2 -0
- package/dist/commands/ledger.test.d.ts.map +1 -0
- package/dist/commands/ledger.test.js +238 -0
- package/dist/commands/ledger.test.js.map +1 -0
- package/dist/commands/lessons.d.ts +73 -0
- package/dist/commands/lessons.d.ts.map +1 -0
- package/dist/commands/lessons.js +97 -0
- package/dist/commands/lessons.js.map +1 -0
- package/dist/commands/lessons.test.d.ts +2 -0
- package/dist/commands/lessons.test.d.ts.map +1 -0
- package/dist/commands/lessons.test.js +146 -0
- package/dist/commands/lessons.test.js.map +1 -0
- package/dist/commands/models.d.ts +49 -0
- package/dist/commands/models.d.ts.map +1 -0
- package/dist/commands/models.js +125 -0
- package/dist/commands/models.js.map +1 -0
- package/dist/commands/report.d.ts +57 -0
- package/dist/commands/report.d.ts.map +1 -0
- package/dist/commands/report.js +164 -0
- package/dist/commands/report.js.map +1 -0
- package/dist/commands/report.test.d.ts +2 -0
- package/dist/commands/report.test.d.ts.map +1 -0
- package/dist/commands/report.test.js +294 -0
- package/dist/commands/report.test.js.map +1 -0
- package/dist/commands/scope.d.ts +34 -0
- package/dist/commands/scope.d.ts.map +1 -0
- package/dist/commands/scope.js +78 -0
- package/dist/commands/scope.js.map +1 -0
- package/dist/commands/scope.test.d.ts +2 -0
- package/dist/commands/scope.test.d.ts.map +1 -0
- package/dist/commands/scope.test.js +98 -0
- package/dist/commands/scope.test.js.map +1 -0
- package/dist/commands/setup.d.ts +31 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +93 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/waivers.d.ts +47 -0
- package/dist/commands/waivers.d.ts.map +1 -0
- package/dist/commands/waivers.js +68 -0
- package/dist/commands/waivers.js.map +1 -0
- package/dist/commands/waivers.test.d.ts +2 -0
- package/dist/commands/waivers.test.d.ts.map +1 -0
- package/dist/commands/waivers.test.js +64 -0
- package/dist/commands/waivers.test.js.map +1 -0
- package/dist/generate/agent.d.ts +19 -0
- package/dist/generate/agent.d.ts.map +1 -0
- package/dist/generate/agent.js +35 -0
- package/dist/generate/agent.js.map +1 -0
- package/dist/generate/agent.test.d.ts +2 -0
- package/dist/generate/agent.test.d.ts.map +1 -0
- package/dist/generate/agent.test.js +245 -0
- package/dist/generate/agent.test.js.map +1 -0
- package/dist/generate/commands.d.ts +15 -0
- package/dist/generate/commands.d.ts.map +1 -0
- package/dist/generate/commands.js +59 -0
- package/dist/generate/commands.js.map +1 -0
- package/dist/generate/lock.d.ts +18 -0
- package/dist/generate/lock.d.ts.map +1 -0
- package/dist/generate/lock.js +26 -0
- package/dist/generate/lock.js.map +1 -0
- package/dist/generate/prompt.d.ts +11 -0
- package/dist/generate/prompt.d.ts.map +1 -0
- package/dist/generate/prompt.js +114 -0
- package/dist/generate/prompt.js.map +1 -0
- package/dist/generate/prompt.test.d.ts +2 -0
- package/dist/generate/prompt.test.d.ts.map +1 -0
- package/dist/generate/prompt.test.js +59 -0
- package/dist/generate/prompt.test.js.map +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +448 -0
- package/dist/index.js.map +1 -0
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +237 -0
- package/dist/index.test.js.map +1 -0
- package/dist/opencode.d.ts +29 -0
- package/dist/opencode.d.ts.map +1 -0
- package/dist/opencode.js +125 -0
- package/dist/opencode.js.map +1 -0
- package/dist/plugin-bundle.test.d.ts +2 -0
- package/dist/plugin-bundle.test.d.ts.map +1 -0
- package/dist/plugin-bundle.test.js +43 -0
- package/dist/plugin-bundle.test.js.map +1 -0
- package/dist/plugin.d.ts +11 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +46 -0
- package/dist/plugin.js.map +1 -0
- package/dist/quality-skills.test.d.ts +2 -0
- package/dist/quality-skills.test.d.ts.map +1 -0
- package/dist/quality-skills.test.js +141 -0
- package/dist/quality-skills.test.js.map +1 -0
- package/dist/report/footprint.d.ts +12 -0
- package/dist/report/footprint.d.ts.map +1 -0
- package/dist/report/footprint.js +121 -0
- package/dist/report/footprint.js.map +1 -0
- package/dist/report/ledger.d.ts +27 -0
- package/dist/report/ledger.d.ts.map +1 -0
- package/dist/report/ledger.js +197 -0
- package/dist/report/ledger.js.map +1 -0
- package/dist/report/oversight.d.ts +21 -0
- package/dist/report/oversight.d.ts.map +1 -0
- package/dist/report/oversight.js +146 -0
- package/dist/report/oversight.js.map +1 -0
- package/dist/report/policy-firing.test.d.ts +2 -0
- package/dist/report/policy-firing.test.d.ts.map +1 -0
- package/dist/report/policy-firing.test.js +68 -0
- package/dist/report/policy-firing.test.js.map +1 -0
- package/dist/report/scope.d.ts +64 -0
- package/dist/report/scope.d.ts.map +1 -0
- package/dist/report/scope.js +146 -0
- package/dist/report/scope.js.map +1 -0
- package/dist/who.d.ts +9 -0
- package/dist/who.d.ts.map +1 -0
- package/dist/who.js +11 -0
- package/dist/who.js.map +1 -0
- package/package.json +54 -4
- package/plugin/openagentsy.js +39478 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { BENCHLM_KEYLESS_URL, LOCK_FILE_NAME, MODELS_DEV_URL, OLLAMA_CLOUD_URL, } from '@openagentsy/models';
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
6
|
+
import { runModels } from './commands/models.js';
|
|
7
|
+
import { main } from './index.js';
|
|
8
|
+
let root;
|
|
9
|
+
let written;
|
|
10
|
+
const ROLES_YAML = `version: 1
|
|
11
|
+
roles:
|
|
12
|
+
builder:
|
|
13
|
+
description: Writes the code.
|
|
14
|
+
mode: subagent
|
|
15
|
+
writes: true
|
|
16
|
+
scope: Write the code.
|
|
17
|
+
guidance: Write the code.
|
|
18
|
+
permissions: {}
|
|
19
|
+
skills: []
|
|
20
|
+
modelProfile:
|
|
21
|
+
primarySignal: coding
|
|
22
|
+
hardRequirements: [tool_calls]
|
|
23
|
+
costStance: quality_first
|
|
24
|
+
effort:
|
|
25
|
+
startVariant: medium
|
|
26
|
+
ceilingVariant: high
|
|
27
|
+
climbTriggers: []
|
|
28
|
+
`;
|
|
29
|
+
function modelMeta(id, name) {
|
|
30
|
+
return {
|
|
31
|
+
id,
|
|
32
|
+
name,
|
|
33
|
+
tool_call: true,
|
|
34
|
+
reasoning: true,
|
|
35
|
+
reasoning_options: [{ type: 'effort', values: ['low', 'medium', 'high'] }],
|
|
36
|
+
limit: { context: 200_000 },
|
|
37
|
+
cost: { input: 1, output: 3 },
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
const MODELS_DEV = {
|
|
41
|
+
'ollama-cloud': {
|
|
42
|
+
id: 'ollama-cloud',
|
|
43
|
+
models: {
|
|
44
|
+
'glm-5.3': modelMeta('glm-5.3', 'GLM 5.3'),
|
|
45
|
+
'glm-5.3-flash': modelMeta('glm-5.3-flash', 'GLM 5.3 Flash'),
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
ollama: {
|
|
49
|
+
id: 'ollama',
|
|
50
|
+
models: {
|
|
51
|
+
'local-model': modelMeta('local-model', 'Local Model'),
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
function benchItem(slug, model, rank) {
|
|
56
|
+
return {
|
|
57
|
+
rank,
|
|
58
|
+
slug,
|
|
59
|
+
canonicalModelKey: slug,
|
|
60
|
+
model,
|
|
61
|
+
creator: 'Test Creator',
|
|
62
|
+
displayScore: 100 - rank,
|
|
63
|
+
evidenceStatus: 'supported',
|
|
64
|
+
scoreConfidence: 3,
|
|
65
|
+
overallRank: rank,
|
|
66
|
+
rankingEligible: true,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const BENCHLM = {
|
|
70
|
+
generatedAt: '2026-10-24T00:00:00.000Z',
|
|
71
|
+
items: [
|
|
72
|
+
benchItem('glm-5-3', 'GLM 5.3', 1),
|
|
73
|
+
benchItem('glm-5-3-flash', 'GLM 5.3 Flash', 2),
|
|
74
|
+
benchItem('local-model', 'Local Model', 3),
|
|
75
|
+
],
|
|
76
|
+
categories: {
|
|
77
|
+
coding: [
|
|
78
|
+
benchItem('glm-5-3', 'GLM 5.3', 1),
|
|
79
|
+
benchItem('glm-5-3-flash', 'GLM 5.3 Flash', 2),
|
|
80
|
+
benchItem('local-model', 'Local Model', 3),
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
const CLOUD_TAGS = { models: [{ name: 'glm-5.3' }, { name: 'glm-5.3-flash' }] };
|
|
85
|
+
const LOCAL_TAGS = { models: [{ name: 'local-model' }] };
|
|
86
|
+
function json(payload) {
|
|
87
|
+
return new Response(JSON.stringify(payload), {
|
|
88
|
+
status: 200,
|
|
89
|
+
headers: { 'Content-Type': 'application/json' },
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
/** The catalogs the selector reads, served without a network. */
|
|
93
|
+
function fakeFetch(url) {
|
|
94
|
+
if (url === MODELS_DEV_URL)
|
|
95
|
+
return Promise.resolve(json(MODELS_DEV));
|
|
96
|
+
if (url === BENCHLM_KEYLESS_URL)
|
|
97
|
+
return Promise.resolve(json(BENCHLM));
|
|
98
|
+
if (url === `${OLLAMA_CLOUD_URL}/api/tags`)
|
|
99
|
+
return Promise.resolve(json(CLOUD_TAGS));
|
|
100
|
+
if (url === 'http://localhost:11434/api/tags')
|
|
101
|
+
return Promise.resolve(json(LOCAL_TAGS));
|
|
102
|
+
return Promise.reject(new Error(`the test does not serve ${url}`));
|
|
103
|
+
}
|
|
104
|
+
async function lockOnDisk() {
|
|
105
|
+
return JSON.parse(await readFile(join(root, LOCK_FILE_NAME), 'utf8'));
|
|
106
|
+
}
|
|
107
|
+
beforeEach(async () => {
|
|
108
|
+
root = await mkdtemp(join(tmpdir(), 'openagentsy-cli-'));
|
|
109
|
+
written = [];
|
|
110
|
+
await writeFile(join(root, 'roles.yaml'), ROLES_YAML);
|
|
111
|
+
vi.spyOn(process.stdout, 'write').mockImplementation((chunk) => {
|
|
112
|
+
written.push(String(chunk));
|
|
113
|
+
return true;
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
afterEach(async () => {
|
|
117
|
+
vi.restoreAllMocks();
|
|
118
|
+
await rm(root, { recursive: true, force: true });
|
|
119
|
+
});
|
|
120
|
+
describe('the CLI', () => {
|
|
121
|
+
it('prints the usage and fails when no command is given', async () => {
|
|
122
|
+
const code = await main([]);
|
|
123
|
+
expect(code).toBe(1);
|
|
124
|
+
expect(written.join('')).toContain('openagentsy <command>');
|
|
125
|
+
});
|
|
126
|
+
it('prints the usage on --help and succeeds', async () => {
|
|
127
|
+
const code = await main(['--help']);
|
|
128
|
+
expect(code).toBe(0);
|
|
129
|
+
expect(written.join('')).toContain('board');
|
|
130
|
+
});
|
|
131
|
+
it('says so when the command is unknown', async () => {
|
|
132
|
+
const code = await main(['nope']);
|
|
133
|
+
expect(code).toBe(1);
|
|
134
|
+
});
|
|
135
|
+
it('shows the board, which is empty on a fresh root', async () => {
|
|
136
|
+
const code = await main(['board', '--root', root]);
|
|
137
|
+
expect(code).toBe(0);
|
|
138
|
+
const output = written.join('');
|
|
139
|
+
expect(output).toContain('records');
|
|
140
|
+
expect(output).toContain('leases');
|
|
141
|
+
expect(output).toContain('budgets');
|
|
142
|
+
});
|
|
143
|
+
it('writes nothing on a dry run of setup', async () => {
|
|
144
|
+
const code = await main(['setup', '--root', root, '--dry-run']);
|
|
145
|
+
expect(code).toBe(0);
|
|
146
|
+
expect(written.join('')).toContain('would write');
|
|
147
|
+
});
|
|
148
|
+
it('leaves the compaction alone by default', async () => {
|
|
149
|
+
// Compaction is off for a memory integration that shrinks the context
|
|
150
|
+
// itself. There is no such integration yet, so a default install that
|
|
151
|
+
// turns compaction off grows a long session without a bound.
|
|
152
|
+
const code = await main(['setup', '--root', root, '--dry-run']);
|
|
153
|
+
expect(code).toBe(0);
|
|
154
|
+
expect(written.join('')).not.toContain('compaction');
|
|
155
|
+
});
|
|
156
|
+
it('turns the compaction off for a memory integration', async () => {
|
|
157
|
+
const code = await main(['setup', '--root', root, '--dry-run', '--magic-context']);
|
|
158
|
+
expect(code).toBe(0);
|
|
159
|
+
expect(written.join('')).toContain('compaction.auto');
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
describe('the models command', () => {
|
|
163
|
+
it('writes the lock when a switch names a provider', async () => {
|
|
164
|
+
const result = await runModels({
|
|
165
|
+
workspace: root,
|
|
166
|
+
stateRoot: root,
|
|
167
|
+
mode: 'switch',
|
|
168
|
+
providers: ['ollama'],
|
|
169
|
+
yes: true,
|
|
170
|
+
fetchImpl: fakeFetch,
|
|
171
|
+
});
|
|
172
|
+
expect(result.written).toBe(true);
|
|
173
|
+
const lock = await lockOnDisk();
|
|
174
|
+
expect(lock.providers).toEqual(['ollama-cloud']);
|
|
175
|
+
expect(lock.roles.builder?.model).toBe('ollama-cloud/glm-5.3');
|
|
176
|
+
});
|
|
177
|
+
it('resolves the alias ollama to the cloud provider', async () => {
|
|
178
|
+
const result = await runModels({
|
|
179
|
+
workspace: root,
|
|
180
|
+
stateRoot: root,
|
|
181
|
+
mode: 'switch',
|
|
182
|
+
providers: ['ollama'],
|
|
183
|
+
yes: true,
|
|
184
|
+
fetchImpl: fakeFetch,
|
|
185
|
+
});
|
|
186
|
+
expect(result.providers).toEqual(['ollama-cloud']);
|
|
187
|
+
});
|
|
188
|
+
it('keeps the providers the lock records when it refreshes', async () => {
|
|
189
|
+
await writeFile(join(root, LOCK_FILE_NAME), JSON.stringify({
|
|
190
|
+
generatedAt: '2026-10-24T00:00:00.000Z',
|
|
191
|
+
providers: ['ollama'],
|
|
192
|
+
roles: { builder: { model: 'ollama/local-model', ladder: [] } },
|
|
193
|
+
}));
|
|
194
|
+
const result = await runModels({
|
|
195
|
+
workspace: root,
|
|
196
|
+
stateRoot: root,
|
|
197
|
+
mode: 'refresh',
|
|
198
|
+
providers: [],
|
|
199
|
+
yes: true,
|
|
200
|
+
fetchImpl: fakeFetch,
|
|
201
|
+
});
|
|
202
|
+
expect(result.providers).toEqual(['ollama']);
|
|
203
|
+
const lock = await lockOnDisk();
|
|
204
|
+
expect(lock.providers).toEqual(['ollama']);
|
|
205
|
+
expect(lock.roles.builder?.model).toBe('ollama/local-model');
|
|
206
|
+
});
|
|
207
|
+
it('takes the flash variant when the preference is asked for', async () => {
|
|
208
|
+
const result = await runModels({
|
|
209
|
+
workspace: root,
|
|
210
|
+
stateRoot: root,
|
|
211
|
+
mode: 'switch',
|
|
212
|
+
providers: ['ollama'],
|
|
213
|
+
preferFlash: true,
|
|
214
|
+
yes: true,
|
|
215
|
+
fetchImpl: fakeFetch,
|
|
216
|
+
});
|
|
217
|
+
expect(result.lock.roles.builder?.model).toBe('ollama-cloud/glm-5.3-flash');
|
|
218
|
+
expect(result.changes[0]?.note).toContain('flash variant of glm-5.3');
|
|
219
|
+
});
|
|
220
|
+
it('names the aliases and what each one means when a provider is unknown', async () => {
|
|
221
|
+
await expect(main(['models', 'init', '--providers', 'nope', '--root', root])).rejects.toThrow(/ollama = the Ollama Cloud models/);
|
|
222
|
+
});
|
|
223
|
+
it('says what the switch touches besides the lock', async () => {
|
|
224
|
+
// The fetch is the test's own: the command reaches the provider
|
|
225
|
+
// catalogue, and a test that reaches models.dev is a test whose time
|
|
226
|
+
// depends on a machine's connection.
|
|
227
|
+
const code = await main(['models', 'switch', 'ollama', '--yes', '--root', root], {
|
|
228
|
+
fetchImpl: fakeFetch,
|
|
229
|
+
});
|
|
230
|
+
expect(code).toBe(0);
|
|
231
|
+
const output = written.join('');
|
|
232
|
+
expect(output).toContain('the switch touches more than the lock');
|
|
233
|
+
expect(output).toContain('openagentsy build');
|
|
234
|
+
expect(output).toContain('OLLAMA_API_KEY');
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type OpenCodeVersion = {
|
|
2
|
+
binary: string;
|
|
3
|
+
raw: string;
|
|
4
|
+
major: number;
|
|
5
|
+
minor: number;
|
|
6
|
+
patch: number;
|
|
7
|
+
};
|
|
8
|
+
export declare function detectOpenCode(): Promise<OpenCodeVersion | undefined>;
|
|
9
|
+
/** Project config file names, in the order OpenCode prefers them. */
|
|
10
|
+
export declare const PROJECT_CONFIG_NAMES: readonly ["opencode.json", "opencode.jsonc"];
|
|
11
|
+
/**
|
|
12
|
+
* Every config file OpenCode reads for a project.
|
|
13
|
+
*
|
|
14
|
+
* OpenCode merges a root config with one in the config directory, so a tool
|
|
15
|
+
* that reads only the root config sees a different system from the one the
|
|
16
|
+
* runtime runs on. The doctor's job is to describe the runtime's system.
|
|
17
|
+
*/
|
|
18
|
+
export declare function findConfigPaths(root: string): Promise<string[]>;
|
|
19
|
+
export type FoundSkill = {
|
|
20
|
+
name: string;
|
|
21
|
+
path: string;
|
|
22
|
+
source: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Find every skill OpenCode could load, and where it came from. The first
|
|
26
|
+
* match for a name wins, matching OpenCode's own resolution order.
|
|
27
|
+
*/
|
|
28
|
+
export declare function findSkills(startDir: string): Promise<FoundSkill[]>;
|
|
29
|
+
//# sourceMappingURL=opencode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../src/opencode.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAsB,cAAc,IAAI,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAgB3E;AAED,qEAAqE;AACrE,eAAO,MAAM,oBAAoB,8CAA+C,CAAC;AAEjF;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAiBrE;AA4BD,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;GAGG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAiBxE"}
|
package/dist/opencode.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { readdir, readFile } from 'node:fs/promises';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
import { promisify } from 'node:util';
|
|
6
|
+
const execFileAsync = promisify(execFile);
|
|
7
|
+
export async function detectOpenCode() {
|
|
8
|
+
try {
|
|
9
|
+
const { stdout } = await execFileAsync('opencode', ['--version'], { timeout: 10_000 });
|
|
10
|
+
const raw = stdout.trim();
|
|
11
|
+
const match = /(\d+)\.(\d+)\.(\d+)/.exec(raw);
|
|
12
|
+
if (!match)
|
|
13
|
+
return undefined;
|
|
14
|
+
return {
|
|
15
|
+
binary: 'opencode',
|
|
16
|
+
raw,
|
|
17
|
+
major: Number(match[1]),
|
|
18
|
+
minor: Number(match[2]),
|
|
19
|
+
patch: Number(match[3]),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** Project config file names, in the order OpenCode prefers them. */
|
|
27
|
+
export const PROJECT_CONFIG_NAMES = ['opencode.json', 'opencode.jsonc'];
|
|
28
|
+
/**
|
|
29
|
+
* Every config file OpenCode reads for a project.
|
|
30
|
+
*
|
|
31
|
+
* OpenCode merges a root config with one in the config directory, so a tool
|
|
32
|
+
* that reads only the root config sees a different system from the one the
|
|
33
|
+
* runtime runs on. The doctor's job is to describe the runtime's system.
|
|
34
|
+
*/
|
|
35
|
+
export async function findConfigPaths(root) {
|
|
36
|
+
const candidates = [
|
|
37
|
+
join(root, 'opencode.json'),
|
|
38
|
+
join(root, 'opencode.jsonc'),
|
|
39
|
+
join(root, '.opencode', 'opencode.json'),
|
|
40
|
+
join(root, '.opencode', 'opencode.jsonc'),
|
|
41
|
+
];
|
|
42
|
+
const found = [];
|
|
43
|
+
for (const path of candidates) {
|
|
44
|
+
try {
|
|
45
|
+
await readFile(path, 'utf8');
|
|
46
|
+
found.push(path);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// A config that is not there is not a config.
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return found;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Directories that hold skills, in the order OpenCode searches them. The
|
|
56
|
+
* first skill found with a given name wins, so a user-level skill can
|
|
57
|
+
* silently shape every project. `openagentsy doctor` prints where each skill
|
|
58
|
+
* came from for exactly that reason.
|
|
59
|
+
*/
|
|
60
|
+
function skillSearchDirs(startDir) {
|
|
61
|
+
const dirs = [];
|
|
62
|
+
let current = startDir;
|
|
63
|
+
for (let depth = 0; depth < 10; depth += 1) {
|
|
64
|
+
dirs.push(join(current, '.opencode', 'skills'));
|
|
65
|
+
dirs.push(join(current, '.claude', 'skills'));
|
|
66
|
+
dirs.push(join(current, '.agents', 'skills'));
|
|
67
|
+
const parent = dirname(current);
|
|
68
|
+
if (parent === current)
|
|
69
|
+
break;
|
|
70
|
+
current = parent;
|
|
71
|
+
}
|
|
72
|
+
dirs.push(join(homedir(), '.config', 'opencode', 'skills'));
|
|
73
|
+
dirs.push(join(homedir(), '.claude', 'skills'));
|
|
74
|
+
dirs.push(join(homedir(), '.agents', 'skills'));
|
|
75
|
+
return dirs;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Find every skill OpenCode could load, and where it came from. The first
|
|
79
|
+
* match for a name wins, matching OpenCode's own resolution order.
|
|
80
|
+
*/
|
|
81
|
+
export async function findSkills(startDir) {
|
|
82
|
+
const seen = new Set();
|
|
83
|
+
const found = [];
|
|
84
|
+
for (const dir of skillSearchDirs(startDir)) {
|
|
85
|
+
const entries = await readDirSafe(dir);
|
|
86
|
+
if (!entries)
|
|
87
|
+
continue;
|
|
88
|
+
for (const entry of entries) {
|
|
89
|
+
const skill = skillOfEntry(dir, entry, seen);
|
|
90
|
+
if (skill) {
|
|
91
|
+
seen.add(skill.name);
|
|
92
|
+
found.push(skill);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return found;
|
|
97
|
+
}
|
|
98
|
+
/** The directory's entries, or nothing when the directory is not there. */
|
|
99
|
+
async function readDirSafe(dir) {
|
|
100
|
+
try {
|
|
101
|
+
return await readdir(dir, { withFileTypes: true });
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The skill one directory entry names, or nothing when the entry is not a
|
|
109
|
+
* skill or its name is already taken.
|
|
110
|
+
*/
|
|
111
|
+
function skillOfEntry(dir, entry, seen) {
|
|
112
|
+
if (entry.isDirectory()) {
|
|
113
|
+
if (seen.has(entry.name))
|
|
114
|
+
return undefined;
|
|
115
|
+
return { name: entry.name, path: join(dir, entry.name, 'SKILL.md'), source: dir };
|
|
116
|
+
}
|
|
117
|
+
// V2 also accepts a flat skills/<name>.md file.
|
|
118
|
+
if (!entry.isFile() || !entry.name.endsWith('.md'))
|
|
119
|
+
return undefined;
|
|
120
|
+
const name = entry.name.replace(/\.md$/, '');
|
|
121
|
+
if (seen.has(name))
|
|
122
|
+
return undefined;
|
|
123
|
+
return { name, path: join(dir, entry.name), source: dir };
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=opencode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode.js","sourceRoot":"","sources":["../src/opencode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAU1C,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACvF,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9C,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAC7B,OAAO;YACL,MAAM,EAAE,UAAU;YAClB,GAAG;YACH,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SACxB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,qEAAqE;AACrE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,eAAe,EAAE,gBAAgB,CAAU,CAAC;AAEjF;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY;IAChD,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC;QAC3B,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC;QAC5B,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,eAAe,CAAC;QACxC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,gBAAgB,CAAC;KAC1C,CAAC;IACF,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;QAAC,MAAM,CAAC;YACP,8CAA8C;QAChD,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,SAAS,eAAe,CAAC,QAAgB;IACvC,MAAM,IAAI,GAAa,EAAE,CAAC;IAE1B,IAAI,OAAO,GAAG,QAAQ,CAAC;IACvB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC3C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;QAChD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC9C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,MAAM,KAAK,OAAO;YAAE,MAAM;QAC9B,OAAO,GAAG,MAAM,CAAC;IACnB,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC5D,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;IAChD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEhD,OAAO,IAAI,CAAC;AACd,CAAC;AAQD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,KAAK,GAAiB,EAAE,CAAC;IAE/B,KAAK,MAAM,GAAG,IAAI,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;YAC7C,IAAI,KAAK,EAAE,CAAC;gBACV,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACrB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,2EAA2E;AAC3E,KAAK,UAAU,WAAW,CAAC,GAAW;IACpC,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CAAC,GAAW,EAAE,KAAa,EAAE,IAAiB;IACjE,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QACxB,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,OAAO,SAAS,CAAC;QAC3C,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACpF,CAAC;IACD,gDAAgD;IAChD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACrE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC7C,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IACrC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-bundle.test.d.ts","sourceRoot":"","sources":["../src/plugin-bundle.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
/**
|
|
5
|
+
* The plugin bundle has to stand on its own.
|
|
6
|
+
*
|
|
7
|
+
* The plugin is loaded by OpenCode from a project's plugin directory, where
|
|
8
|
+
* bare imports do not resolve, so it travels as one file. A dynamic import
|
|
9
|
+
* that the bundler leaves as a chunk produces a second file that the copy
|
|
10
|
+
* does not take, and the plugin then fails to load at the worst possible
|
|
11
|
+
* moment: the lease guard never registers and every write goes through.
|
|
12
|
+
*
|
|
13
|
+
* Nothing else in the test suite loads the bundle, so this is the one place
|
|
14
|
+
* that can see it.
|
|
15
|
+
*/
|
|
16
|
+
const bundlePath = fileURLToPath(new URL('../plugin/openagentsy.js', import.meta.url));
|
|
17
|
+
describe('the plugin bundle', () => {
|
|
18
|
+
it('imports nothing from a path next to it', async () => {
|
|
19
|
+
const bundle = await readFile(bundlePath, 'utf8');
|
|
20
|
+
// The statements that pull in a relative path, and nothing else. The
|
|
21
|
+
// bundle carries the text of the packages it inlines, and a doc comment
|
|
22
|
+
// in one of them shows an import of its own; a statement that does not
|
|
23
|
+
// start a line is prose, not an import.
|
|
24
|
+
const relative = bundle.match(/^(?!\s*\*)\s*(?:(?:import|export)[^\n;]*?from|import\s*\()\s*['"]\.[^'"]+['"]/gm);
|
|
25
|
+
expect(relative ?? []).toEqual([]);
|
|
26
|
+
});
|
|
27
|
+
it('does not carry the TypeScript compiler', async () => {
|
|
28
|
+
const bundle = await readFile(bundlePath, 'utf8');
|
|
29
|
+
// The comment rules need a TypeScript parse to find the comments of a
|
|
30
|
+
// file. The plugin runs a check on every write, so the compiler is not
|
|
31
|
+
// in the bundle: the comment lint runs in the quality tool and in the
|
|
32
|
+
// audit command, where a parse is paid for on demand. These are names
|
|
33
|
+
// of the compiler's own API, and nothing else in the bundle has them.
|
|
34
|
+
expect(bundle).not.toContain('getPreEmitDiagnostics');
|
|
35
|
+
expect(bundle).not.toContain('createTypeChecker');
|
|
36
|
+
});
|
|
37
|
+
it('is the file the setup command copies out', async () => {
|
|
38
|
+
const source = await readFile(fileURLToPath(new URL('../../adapter-opencode/dist/index.js', import.meta.url)), 'utf8');
|
|
39
|
+
const bundle = await readFile(bundlePath, 'utf8');
|
|
40
|
+
expect(bundle).toBe(source);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
//# sourceMappingURL=plugin-bundle.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-bundle.test.js","sourceRoot":"","sources":["../src/plugin-bundle.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,0BAA0B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAEvF,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAClD,qEAAqE;QACrE,wEAAwE;QACxE,uEAAuE;QACvE,wCAAwC;QACxC,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAC3B,iFAAiF,CAClF,CAAC;QACF,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAClD,sEAAsE;QACtE,uEAAuE;QACvE,sEAAsE;QACtE,sEAAsE;QACtE,sEAAsE;QACtE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;QACtD,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAC3B,aAAa,CAAC,IAAI,GAAG,CAAC,sCAAsC,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAC/E,MAAM,CACP,CAAC;QACF,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAClD,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** The plugin bundle, or undefined when it has not been built. */
|
|
2
|
+
export declare function findPluginBundle(): Promise<string | undefined>;
|
|
3
|
+
/**
|
|
4
|
+
* Install the plugin into a project's OpenCode plugin directory.
|
|
5
|
+
*
|
|
6
|
+
* The plugin is a self contained bundle, because a plugin file is loaded from
|
|
7
|
+
* the config directory where bare imports do not resolve, and the plugin
|
|
8
|
+
* runtime has no sqlite module.
|
|
9
|
+
*/
|
|
10
|
+
export declare function installPlugin(root: string, dryRun: boolean): Promise<string | undefined>;
|
|
11
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AA4BA,kEAAkE;AAClE,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAYpE;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAU9F"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { copyFile, mkdir, stat } from 'node:fs/promises';
|
|
2
|
+
import { dirname, join, resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
/**
|
|
5
|
+
* Where the plugin bundle lives.
|
|
6
|
+
*
|
|
7
|
+
* The bundle is two things at once: the file the OpenCode plugin loader
|
|
8
|
+
* reads, and the copy the published package ships. In a checkout it is built
|
|
9
|
+
* by the adapter package; in an installed package it sits next to this file.
|
|
10
|
+
* The first place that has one wins.
|
|
11
|
+
*/
|
|
12
|
+
const CANDIDATES = [
|
|
13
|
+
// An installed package: the bundle is shipped in the plugin directory.
|
|
14
|
+
resolve(dirname(fileURLToPath(import.meta.url)), '..', 'plugin', 'openagentsy.js'),
|
|
15
|
+
// A checkout: the adapter package builds it.
|
|
16
|
+
resolve(process.cwd(), 'packages', 'adapter-opencode', 'dist', 'index.js'),
|
|
17
|
+
resolve(dirname(fileURLToPath(import.meta.url)), '..', '..', '..', 'adapter-opencode', 'dist', 'index.js'),
|
|
18
|
+
];
|
|
19
|
+
/** The plugin bundle, or undefined when it has not been built. */
|
|
20
|
+
export async function findPluginBundle() {
|
|
21
|
+
for (const candidate of CANDIDATES) {
|
|
22
|
+
if (await stat(candidate).then(() => true, () => false)) {
|
|
23
|
+
return candidate;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Install the plugin into a project's OpenCode plugin directory.
|
|
30
|
+
*
|
|
31
|
+
* The plugin is a self contained bundle, because a plugin file is loaded from
|
|
32
|
+
* the config directory where bare imports do not resolve, and the plugin
|
|
33
|
+
* runtime has no sqlite module.
|
|
34
|
+
*/
|
|
35
|
+
export async function installPlugin(root, dryRun) {
|
|
36
|
+
const source = await findPluginBundle();
|
|
37
|
+
if (source === undefined)
|
|
38
|
+
return undefined;
|
|
39
|
+
const target = join(root, '.opencode', 'plugins', 'openagentsy.js');
|
|
40
|
+
if (!dryRun) {
|
|
41
|
+
await mkdir(dirname(target), { recursive: true });
|
|
42
|
+
await copyFile(source, target);
|
|
43
|
+
}
|
|
44
|
+
return target;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC;;;;;;;GAOG;AACH,MAAM,UAAU,GAAG;IACjB,uEAAuE;IACvE,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,gBAAgB,CAAC;IAClF,6CAA6C;IAC7C,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,EAAE,UAAU,CAAC;IAC1E,OAAO,CACL,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EACvC,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,kBAAkB,EAClB,MAAM,EACN,UAAU,CACX;CACF,CAAC;AAEF,kEAAkE;AAClE,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IACE,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CACxB,GAAG,EAAE,CAAC,IAAI,EACV,GAAG,EAAE,CAAC,KAAK,CACZ,EACD,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY,EAAE,MAAe;IAC/D,MAAM,MAAM,GAAG,MAAM,gBAAgB,EAAE,CAAC;IACxC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAE3C,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;IACpE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,MAAM,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality-skills.test.d.ts","sourceRoot":"","sources":["../src/quality-skills.test.ts"],"names":[],"mappings":""}
|