@otto-assistant/otto 0.1.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.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +257 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +39 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +264 -0
- package/dist/config.js.map +1 -0
- package/dist/config.test.d.ts +2 -0
- package/dist/config.test.d.ts.map +1 -0
- package/dist/config.test.js +202 -0
- package/dist/config.test.js.map +1 -0
- package/dist/detect.d.ts +9 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +40 -0
- package/dist/detect.js.map +1 -0
- package/dist/detect.test.d.ts +2 -0
- package/dist/detect.test.d.ts.map +1 -0
- package/dist/detect.test.js +25 -0
- package/dist/detect.test.js.map +1 -0
- package/dist/health.d.ts +27 -0
- package/dist/health.d.ts.map +1 -0
- package/dist/health.js +78 -0
- package/dist/health.js.map +1 -0
- package/dist/health.test.d.ts +2 -0
- package/dist/health.test.d.ts.map +1 -0
- package/dist/health.test.js +33 -0
- package/dist/health.test.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -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 +8 -0
- package/dist/index.test.js.map +1 -0
- package/dist/installer.d.ts +10 -0
- package/dist/installer.d.ts.map +1 -0
- package/dist/installer.js +50 -0
- package/dist/installer.js.map +1 -0
- package/dist/installer.test.d.ts +2 -0
- package/dist/installer.test.d.ts.map +1 -0
- package/dist/installer.test.js +43 -0
- package/dist/installer.test.js.map +1 -0
- package/dist/lifecycle.d.ts +4 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +30 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/lifecycle.test.d.ts +2 -0
- package/dist/lifecycle.test.d.ts.map +1 -0
- package/dist/lifecycle.test.js +19 -0
- package/dist/lifecycle.test.js.map +1 -0
- package/dist/manifest.d.ts +18 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +30 -0
- package/dist/manifest.js.map +1 -0
- package/dist/sync.d.ts +10 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +39 -0
- package/dist/sync.js.map +1 -0
- package/package.json +41 -0
- package/src/cli.ts +291 -0
- package/src/config.test.ts +237 -0
- package/src/config.ts +362 -0
- package/src/detect.test.ts +28 -0
- package/src/detect.ts +52 -0
- package/src/health.test.ts +39 -0
- package/src/health.ts +114 -0
- package/src/index.test.ts +8 -0
- package/src/index.ts +28 -0
- package/src/installer.test.ts +52 -0
- package/src/installer.ts +62 -0
- package/src/lifecycle.test.ts +22 -0
- package/src/lifecycle.ts +30 -0
- package/src/manifest.ts +42 -0
- package/src/sync.ts +53 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { mergePlugins, readOttoConfig, writeOttoConfig, OTTO_DEFAULTS, buildSubagentThreadPolicy, mergeAgentPrompts, ensureSubagentThreadSkill, readOpenCodeConfigState, } from "./config.js";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
describe("config", () => {
|
|
7
|
+
it("adds plugin to empty config", () => {
|
|
8
|
+
const config = {};
|
|
9
|
+
const result = mergePlugins(config, "opencode-agent-memory");
|
|
10
|
+
expect(result.plugin).toEqual(["opencode-agent-memory"]);
|
|
11
|
+
});
|
|
12
|
+
it("appends plugin to existing array", () => {
|
|
13
|
+
const config = { plugin: ["existing-plugin"] };
|
|
14
|
+
const result = mergePlugins(config, "opencode-agent-memory");
|
|
15
|
+
expect(result.plugin).toEqual(["existing-plugin", "opencode-agent-memory"]);
|
|
16
|
+
});
|
|
17
|
+
it("does not duplicate existing plugin", () => {
|
|
18
|
+
const config = { plugin: ["opencode-agent-memory"] };
|
|
19
|
+
const result = mergePlugins(config, "opencode-agent-memory");
|
|
20
|
+
expect(result.plugin).toEqual(["opencode-agent-memory"]);
|
|
21
|
+
});
|
|
22
|
+
it("preserves other config fields", () => {
|
|
23
|
+
const config = {
|
|
24
|
+
model: "gpt-4",
|
|
25
|
+
plugin: ["existing"],
|
|
26
|
+
provider: { cursor: { name: "Cursor" } },
|
|
27
|
+
};
|
|
28
|
+
const result = mergePlugins(config, "opencode-agent-memory");
|
|
29
|
+
expect(result.model).toBe("gpt-4");
|
|
30
|
+
expect(result.provider).toEqual({ cursor: { name: "Cursor" } });
|
|
31
|
+
expect(result.plugin).toEqual(["existing", "opencode-agent-memory"]);
|
|
32
|
+
});
|
|
33
|
+
it("readOttoConfig returns defaults when otto.json missing", () => {
|
|
34
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "otto-test-"));
|
|
35
|
+
try {
|
|
36
|
+
const result = readOttoConfig(tmpDir);
|
|
37
|
+
expect(result.subagentThreads).toEqual({
|
|
38
|
+
enabled: true,
|
|
39
|
+
askBeforeDelete: true,
|
|
40
|
+
autoDeleteOnComplete: false,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
it("writeOttoConfig + readOttoConfig round-trip", () => {
|
|
48
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "otto-test-"));
|
|
49
|
+
try {
|
|
50
|
+
const config = {
|
|
51
|
+
subagentThreads: {
|
|
52
|
+
enabled: false,
|
|
53
|
+
askBeforeDelete: false,
|
|
54
|
+
autoDeleteOnComplete: true,
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
const written = writeOttoConfig(config, tmpDir);
|
|
58
|
+
expect(written).toBe(true);
|
|
59
|
+
const read = readOttoConfig(tmpDir);
|
|
60
|
+
expect(read.subagentThreads).toEqual({
|
|
61
|
+
enabled: false,
|
|
62
|
+
askBeforeDelete: false,
|
|
63
|
+
autoDeleteOnComplete: true,
|
|
64
|
+
});
|
|
65
|
+
// Idempotent
|
|
66
|
+
const writtenAgain = writeOttoConfig(config, tmpDir);
|
|
67
|
+
expect(writtenAgain).toBe(false);
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
it("readOttoConfig fills defaults for partial config", () => {
|
|
74
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "otto-test-"));
|
|
75
|
+
try {
|
|
76
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
77
|
+
fs.writeFileSync(path.join(tmpDir, "otto.json"), JSON.stringify({ subagentThreads: { enabled: false } }, null, 2) + "\n", "utf-8");
|
|
78
|
+
const result = readOttoConfig(tmpDir);
|
|
79
|
+
expect(result.subagentThreads.enabled).toBe(false);
|
|
80
|
+
expect(result.subagentThreads.askBeforeDelete).toBe(true); // default
|
|
81
|
+
expect(result.subagentThreads.autoDeleteOnComplete).toBe(false); // default
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
it("policy includes kimaki send commands when enabled", () => {
|
|
88
|
+
const ottoConfig = {
|
|
89
|
+
subagentThreads: { enabled: true, askBeforeDelete: true, autoDeleteOnComplete: false },
|
|
90
|
+
};
|
|
91
|
+
const policy = buildSubagentThreadPolicy(ottoConfig);
|
|
92
|
+
expect(policy).toContain("Otto subagent policy (must follow):");
|
|
93
|
+
expect(policy).toContain("subagent_threads_enabled: true");
|
|
94
|
+
expect(policy).toContain("kimaki send");
|
|
95
|
+
expect(policy).toContain("--channel");
|
|
96
|
+
expect(policy).toContain("--wait");
|
|
97
|
+
expect(policy).toContain("ask the user");
|
|
98
|
+
});
|
|
99
|
+
it("policy is short when threads disabled", () => {
|
|
100
|
+
const ottoConfig = {
|
|
101
|
+
subagentThreads: { enabled: false, askBeforeDelete: true, autoDeleteOnComplete: false },
|
|
102
|
+
};
|
|
103
|
+
const policy = buildSubagentThreadPolicy(ottoConfig);
|
|
104
|
+
expect(policy).toContain("subagent_threads_enabled: false");
|
|
105
|
+
expect(policy).toContain("without creating Discord threads");
|
|
106
|
+
expect(policy).not.toContain("kimaki send");
|
|
107
|
+
});
|
|
108
|
+
it("policy includes auto-archive when autoDeleteOnComplete is true", () => {
|
|
109
|
+
const ottoConfig = {
|
|
110
|
+
subagentThreads: { enabled: true, askBeforeDelete: false, autoDeleteOnComplete: true },
|
|
111
|
+
};
|
|
112
|
+
const policy = buildSubagentThreadPolicy(ottoConfig);
|
|
113
|
+
expect(policy).toContain("auto_delete_on_complete: true");
|
|
114
|
+
expect(policy).toContain("kimaki session archive");
|
|
115
|
+
expect(policy).not.toContain("ask the user");
|
|
116
|
+
});
|
|
117
|
+
it("injects policy into existing agent prompt", () => {
|
|
118
|
+
const config = {
|
|
119
|
+
agent: { build: { prompt: "existing rule" } },
|
|
120
|
+
};
|
|
121
|
+
const ottoConfig = OTTO_DEFAULTS;
|
|
122
|
+
const policy = buildSubagentThreadPolicy(ottoConfig);
|
|
123
|
+
const result = mergeAgentPrompts(config, policy);
|
|
124
|
+
const prompt = result.agent.build.prompt;
|
|
125
|
+
expect(prompt).toContain("existing rule");
|
|
126
|
+
expect(prompt).toContain("Otto subagent policy (must follow):");
|
|
127
|
+
expect(prompt).toContain("subagent_threads_enabled: true");
|
|
128
|
+
});
|
|
129
|
+
it("does not duplicate policy when already present", () => {
|
|
130
|
+
const ottoConfig = OTTO_DEFAULTS;
|
|
131
|
+
const policy = buildSubagentThreadPolicy(ottoConfig);
|
|
132
|
+
const config = {
|
|
133
|
+
agent: { build: { prompt: policy } },
|
|
134
|
+
};
|
|
135
|
+
const result = mergeAgentPrompts(config, policy);
|
|
136
|
+
const prompt = result.agent.build.prompt ?? "";
|
|
137
|
+
expect(prompt.match(/Otto subagent policy \(must follow\):/g)?.length).toBe(1);
|
|
138
|
+
});
|
|
139
|
+
it("creates build agent with policy when agent section is empty", () => {
|
|
140
|
+
const ottoConfig = OTTO_DEFAULTS;
|
|
141
|
+
const policy = buildSubagentThreadPolicy(ottoConfig);
|
|
142
|
+
const result = mergeAgentPrompts({}, policy);
|
|
143
|
+
const agents = result.agent;
|
|
144
|
+
expect(agents.build?.prompt).toContain("Otto subagent policy (must follow):");
|
|
145
|
+
});
|
|
146
|
+
it("readOpenCodeConfigState returns missing when file absent", () => {
|
|
147
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "otto-test-"));
|
|
148
|
+
try {
|
|
149
|
+
const result = readOpenCodeConfigState(tmpDir);
|
|
150
|
+
expect(result.status).toBe("missing");
|
|
151
|
+
expect(result.config).toEqual({});
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
it("readOpenCodeConfigState returns ok for valid JSON", () => {
|
|
158
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "otto-test-"));
|
|
159
|
+
try {
|
|
160
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
161
|
+
fs.writeFileSync(path.join(tmpDir, "opencode.json"), "{\"model\":\"x\"}\n", "utf-8");
|
|
162
|
+
const result = readOpenCodeConfigState(tmpDir);
|
|
163
|
+
expect(result.status).toBe("ok");
|
|
164
|
+
expect(result.config).toEqual({ model: "x" });
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
it("readOpenCodeConfigState returns invalid for broken JSON", () => {
|
|
171
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "otto-test-"));
|
|
172
|
+
try {
|
|
173
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
174
|
+
fs.writeFileSync(path.join(tmpDir, "opencode.json"), "{not json", "utf-8");
|
|
175
|
+
const result = readOpenCodeConfigState(tmpDir);
|
|
176
|
+
expect(result.status).toBe("invalid");
|
|
177
|
+
expect(result.config).toEqual({});
|
|
178
|
+
}
|
|
179
|
+
finally {
|
|
180
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
it("ensureSubagentThreadSkill creates skill file", () => {
|
|
184
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "otto-test-"));
|
|
185
|
+
try {
|
|
186
|
+
const created = ensureSubagentThreadSkill(tmpDir);
|
|
187
|
+
expect(created).toBe(true);
|
|
188
|
+
const skillPath = path.join(tmpDir, "skills", "otto-subagent-threads", "SKILL.md");
|
|
189
|
+
const content = fs.readFileSync(skillPath, "utf-8");
|
|
190
|
+
expect(content).toContain("name: otto-subagent-threads");
|
|
191
|
+
expect(content).toContain("kimaki send");
|
|
192
|
+
expect(content).toContain("kimaki session archive");
|
|
193
|
+
// Idempotent — second call returns false
|
|
194
|
+
const second = ensureSubagentThreadSkill(tmpDir);
|
|
195
|
+
expect(second).toBe(false);
|
|
196
|
+
}
|
|
197
|
+
finally {
|
|
198
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
//# sourceMappingURL=config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.test.js","sourceRoot":"","sources":["../src/config.test.ts"],"names":[],"mappings":"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"}
|
package/dist/detect.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface InstalledPackage {
|
|
2
|
+
name: string;
|
|
3
|
+
installed: string | null;
|
|
4
|
+
}
|
|
5
|
+
/** For tests: reset cached `npm list -g` result between cases. */
|
|
6
|
+
export declare function clearGlobalNpmListCache(): void;
|
|
7
|
+
export declare function getInstalledVersion(packageName: string): string | null;
|
|
8
|
+
export declare function detectPackage(name: string): Promise<InstalledPackage>;
|
|
9
|
+
//# sourceMappingURL=detect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAgCD,kEAAkE;AAClE,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEtE;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAK3E"}
|
package/dist/detect.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
let globalVersionCache = null;
|
|
3
|
+
function loadGlobalPackageVersions() {
|
|
4
|
+
if (globalVersionCache) {
|
|
5
|
+
return globalVersionCache;
|
|
6
|
+
}
|
|
7
|
+
const map = new Map();
|
|
8
|
+
try {
|
|
9
|
+
const output = execFileSync(process.platform === "win32" ? "npm.cmd" : "npm", ["list", "-g", "--json", "--depth=0"], {
|
|
10
|
+
encoding: "utf-8",
|
|
11
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
12
|
+
});
|
|
13
|
+
const parsed = JSON.parse(output);
|
|
14
|
+
const deps = parsed.dependencies ?? {};
|
|
15
|
+
for (const [name, info] of Object.entries(deps)) {
|
|
16
|
+
if (info?.version) {
|
|
17
|
+
map.set(name, info.version);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// leave map empty — callers treat missing entries as not installed
|
|
23
|
+
}
|
|
24
|
+
globalVersionCache = map;
|
|
25
|
+
return map;
|
|
26
|
+
}
|
|
27
|
+
/** For tests: reset cached `npm list -g` result between cases. */
|
|
28
|
+
export function clearGlobalNpmListCache() {
|
|
29
|
+
globalVersionCache = null;
|
|
30
|
+
}
|
|
31
|
+
export function getInstalledVersion(packageName) {
|
|
32
|
+
return loadGlobalPackageVersions().get(packageName) ?? null;
|
|
33
|
+
}
|
|
34
|
+
export async function detectPackage(name) {
|
|
35
|
+
return {
|
|
36
|
+
name,
|
|
37
|
+
installed: getInstalledVersion(name),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAOjD,IAAI,kBAAkB,GAA+B,IAAI,CAAA;AAEzD,SAAS,yBAAyB;IAChC,IAAI,kBAAkB,EAAE,CAAC;QACvB,OAAO,kBAAkB,CAAA;IAC3B,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAA;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,YAAY,CACzB,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,EAChD,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,EACrC;YACE,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CACF,CAAA;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAA4D,CAAA;QAC5F,MAAM,IAAI,GAAG,MAAM,CAAC,YAAY,IAAI,EAAE,CAAA;QACtC,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAChD,IAAI,IAAI,EAAE,OAAO,EAAE,CAAC;gBAClB,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;YAC7B,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,mEAAmE;IACrE,CAAC;IACD,kBAAkB,GAAG,GAAG,CAAA;IACxB,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,uBAAuB;IACrC,kBAAkB,GAAG,IAAI,CAAA;AAC3B,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,OAAO,yBAAyB,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,IAAI,CAAA;AAC7D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY;IAC9C,OAAO;QACL,IAAI;QACJ,SAAS,EAAE,mBAAmB,CAAC,IAAI,CAAC;KACrC,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.test.d.ts","sourceRoot":"","sources":["../src/detect.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { getInstalledVersion, detectPackage } from "./detect.js";
|
|
3
|
+
describe("detect", () => {
|
|
4
|
+
it("returns null for non-existent package", () => {
|
|
5
|
+
const result = getInstalledVersion("nonexistent-package-xyz-123");
|
|
6
|
+
expect(result).toBeNull();
|
|
7
|
+
});
|
|
8
|
+
// These tests require kimaki to be globally installed (skipped on CI)
|
|
9
|
+
const describeIfInstalled = process.env.CI ? describe.skip : describe;
|
|
10
|
+
describeIfInstalled("with kimaki installed", () => {
|
|
11
|
+
it("detects an existing global package", () => {
|
|
12
|
+
const result = getInstalledVersion("kimaki");
|
|
13
|
+
expect(result).not.toBeNull();
|
|
14
|
+
expect(result).toMatch(/^\d+\.\d+\.\d+/);
|
|
15
|
+
});
|
|
16
|
+
it("detectPackage returns full info", async () => {
|
|
17
|
+
const result = await detectPackage("kimaki");
|
|
18
|
+
expect(result).toEqual({
|
|
19
|
+
name: "kimaki",
|
|
20
|
+
installed: expect.any(String),
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
//# sourceMappingURL=detect.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.test.js","sourceRoot":"","sources":["../src/detect.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAyB,MAAM,aAAa,CAAA;AAEvF,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;IACtB,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,MAAM,GAAG,mBAAmB,CAAC,6BAA6B,CAAC,CAAA;QACjE,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAA;IAC3B,CAAC,CAAC,CAAA;IAEF,sEAAsE;IACtE,MAAM,mBAAmB,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAA;IAErE,mBAAmB,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAChD,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,MAAM,MAAM,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAA;YAC5C,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAA;YAC7B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAA;QAC1C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;YAC/C,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,QAAQ,CAAC,CAAA;YAC5C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;gBACrB,IAAI,EAAE,QAAQ;gBACd,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;aAC9B,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
package/dist/health.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface HealthResult {
|
|
2
|
+
name: string;
|
|
3
|
+
status: "ok" | "warn" | "error";
|
|
4
|
+
message: string;
|
|
5
|
+
}
|
|
6
|
+
export interface PackageCheck {
|
|
7
|
+
name: string;
|
|
8
|
+
installed: string | null;
|
|
9
|
+
required: string;
|
|
10
|
+
status: "ok" | "missing";
|
|
11
|
+
}
|
|
12
|
+
export declare function checkPackagePresence(): PackageCheck[];
|
|
13
|
+
export interface ConfigHealth {
|
|
14
|
+
opencodeJson: "ok" | "missing" | "error";
|
|
15
|
+
ottoJson: "ok" | "missing";
|
|
16
|
+
agentMemoryJson: "ok" | "missing";
|
|
17
|
+
memoryPluginEnabled: boolean;
|
|
18
|
+
subagentPolicyInjected: boolean;
|
|
19
|
+
subagentThreadsEnabled: boolean;
|
|
20
|
+
subagentThreadsAskBeforeDelete: boolean;
|
|
21
|
+
subagentThreadsAutoDelete: boolean;
|
|
22
|
+
plugins: string[];
|
|
23
|
+
kimakiRunning: boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare function checkConfigHealth(): ConfigHealth;
|
|
26
|
+
export declare function checkDirectoryHealth(): HealthResult[];
|
|
27
|
+
//# sourceMappingURL=health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../src/health.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,OAAO,CAAA;IAC/B,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,IAAI,GAAG,SAAS,CAAA;CACzB;AAoBD,wBAAgB,oBAAoB,IAAI,YAAY,EAAE,CAKrD;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,IAAI,GAAG,SAAS,GAAG,OAAO,CAAA;IACxC,QAAQ,EAAE,IAAI,GAAG,SAAS,CAAA;IAC1B,eAAe,EAAE,IAAI,GAAG,SAAS,CAAA;IACjC,mBAAmB,EAAE,OAAO,CAAA;IAC5B,sBAAsB,EAAE,OAAO,CAAA;IAC/B,sBAAsB,EAAE,OAAO,CAAA;IAC/B,8BAA8B,EAAE,OAAO,CAAA;IACvC,yBAAyB,EAAE,OAAO,CAAA;IAClC,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,aAAa,EAAE,OAAO,CAAA;CACvB;AAED,wBAAgB,iBAAiB,IAAI,YAAY,CAoChD;AAED,wBAAgB,oBAAoB,IAAI,YAAY,EAAE,CAiBrD"}
|
package/dist/health.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { getInstalledVersion } from "./detect.js";
|
|
4
|
+
import { readOpenCodeConfigState, readOttoConfig } from "./config.js";
|
|
5
|
+
import { MANIFEST, OPENCODE_CONFIG_DIR, KIMAKI_DATA_DIR } from "./manifest.js";
|
|
6
|
+
import { isKimakiRunning } from "./lifecycle.js";
|
|
7
|
+
const SUBAGENT_POLICY_MARKER = "Otto subagent policy (must follow):";
|
|
8
|
+
function subagentPolicyInjectedInPrompts(config) {
|
|
9
|
+
const agent = config.agent;
|
|
10
|
+
if (!agent || typeof agent !== "object" || Array.isArray(agent)) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
for (const value of Object.values(agent)) {
|
|
14
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
15
|
+
const prompt = value.prompt;
|
|
16
|
+
if (typeof prompt === "string" && prompt.includes(SUBAGENT_POLICY_MARKER)) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
export function checkPackagePresence() {
|
|
24
|
+
return Object.entries(MANIFEST.packages).map(([name, required]) => {
|
|
25
|
+
const installed = getInstalledVersion(name);
|
|
26
|
+
return { name, installed, required, status: installed ? "ok" : "missing" };
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export function checkConfigHealth() {
|
|
30
|
+
const configDir = OPENCODE_CONFIG_DIR();
|
|
31
|
+
const agentMemoryPath = path.join(configDir, "agent-memory.json");
|
|
32
|
+
const ottoJsonPath = path.join(configDir, "otto.json");
|
|
33
|
+
const state = readOpenCodeConfigState();
|
|
34
|
+
const opencodeJson = state.status === "missing" ? "missing" : state.status === "invalid" ? "error" : "ok";
|
|
35
|
+
const agentMemoryJson = fs.existsSync(agentMemoryPath) ? "ok" : "missing";
|
|
36
|
+
const ottoJson = fs.existsSync(ottoJsonPath) ? "ok" : "missing";
|
|
37
|
+
const config = state.status === "ok" ? state.config : {};
|
|
38
|
+
const configuredPlugins = config.plugin ?? [];
|
|
39
|
+
const memoryPluginEnabled = configuredPlugins.includes("opencode-agent-memory");
|
|
40
|
+
const subagentPolicyInjected = subagentPolicyInjectedInPrompts(config);
|
|
41
|
+
// Read Otto config from otto.json (separate from opencode.json)
|
|
42
|
+
const ottoConfig = readOttoConfig();
|
|
43
|
+
const subagentThreadsEnabled = ottoConfig.subagentThreads.enabled;
|
|
44
|
+
const subagentThreadsAskBeforeDelete = ottoConfig.subagentThreads.askBeforeDelete;
|
|
45
|
+
const subagentThreadsAutoDelete = ottoConfig.subagentThreads.autoDeleteOnComplete;
|
|
46
|
+
const kimakiRunning = isKimakiRunning();
|
|
47
|
+
return {
|
|
48
|
+
opencodeJson,
|
|
49
|
+
ottoJson,
|
|
50
|
+
agentMemoryJson,
|
|
51
|
+
memoryPluginEnabled,
|
|
52
|
+
subagentPolicyInjected,
|
|
53
|
+
subagentThreadsEnabled,
|
|
54
|
+
subagentThreadsAskBeforeDelete,
|
|
55
|
+
subagentThreadsAutoDelete,
|
|
56
|
+
plugins: configuredPlugins,
|
|
57
|
+
kimakiRunning,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export function checkDirectoryHealth() {
|
|
61
|
+
const results = [];
|
|
62
|
+
const dirs = [
|
|
63
|
+
{ p: OPENCODE_CONFIG_DIR(), label: "opencode config dir" },
|
|
64
|
+
{ p: path.join(OPENCODE_CONFIG_DIR(), "memory"), label: "opencode memory dir" },
|
|
65
|
+
{ p: path.join(OPENCODE_CONFIG_DIR(), "journal"), label: "opencode journal dir" },
|
|
66
|
+
{ p: KIMAKI_DATA_DIR(), label: "kimaki data dir" },
|
|
67
|
+
];
|
|
68
|
+
for (const { p, label } of dirs) {
|
|
69
|
+
if (fs.existsSync(p)) {
|
|
70
|
+
results.push({ name: label, status: "ok", message: `exists: ${p}` });
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
results.push({ name: label, status: "warn", message: `missing: ${p}` });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return results;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../src/health.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.test.d.ts","sourceRoot":"","sources":["../src/health.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { checkPackagePresence, checkConfigHealth, checkDirectoryHealth, } from "./health.js";
|
|
3
|
+
describe("health", () => {
|
|
4
|
+
it("checkPackagePresence returns results for all manifest packages", { timeout: 30_000 }, () => {
|
|
5
|
+
const results = checkPackagePresence();
|
|
6
|
+
expect(results).toHaveLength(2); // opencode-ai + kimaki (not opencode-agent-memory — it's a plugin)
|
|
7
|
+
for (const r of results) {
|
|
8
|
+
expect(r).toHaveProperty("name");
|
|
9
|
+
expect(r).toHaveProperty("installed");
|
|
10
|
+
expect(r).toHaveProperty("status");
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
it("checkConfigHealth returns structured result", () => {
|
|
14
|
+
const result = checkConfigHealth();
|
|
15
|
+
expect(result).toHaveProperty("opencodeJson");
|
|
16
|
+
expect(result).toHaveProperty("ottoJson");
|
|
17
|
+
expect(result).toHaveProperty("agentMemoryJson");
|
|
18
|
+
expect(result).toHaveProperty("memoryPluginEnabled");
|
|
19
|
+
expect(result).toHaveProperty("subagentPolicyInjected");
|
|
20
|
+
expect(result).toHaveProperty("subagentThreadsEnabled");
|
|
21
|
+
expect(result).toHaveProperty("subagentThreadsAskBeforeDelete");
|
|
22
|
+
expect(result).toHaveProperty("subagentThreadsAutoDelete");
|
|
23
|
+
expect(result).toHaveProperty("plugins");
|
|
24
|
+
expect(result).toHaveProperty("kimakiRunning");
|
|
25
|
+
expect(Array.isArray(result.plugins)).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
it("checkDirectoryHealth returns results", () => {
|
|
28
|
+
const results = checkDirectoryHealth();
|
|
29
|
+
expect(Array.isArray(results)).toBe(true);
|
|
30
|
+
expect(results.length).toBeGreaterThan(0);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
//# sourceMappingURL=health.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.test.js","sourceRoot":"","sources":["../src/health.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,aAAa,CAAA;AAEpB,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;IACtB,EAAE,CAAC,gEAAgE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE;QAC7F,MAAM,OAAO,GAAG,oBAAoB,EAAE,CAAA;QACtC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA,CAAC,mEAAmE;QACnG,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,MAAM,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,CAAA;YAChC,MAAM,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,WAAW,CAAC,CAAA;YACrC,MAAM,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAA;QACpC,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAA;QAClC,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,cAAc,CAAC,CAAA;QAC7C,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,CAAA;QACzC,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAA;QAChD,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,qBAAqB,CAAC,CAAA;QACpD,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAA;QACvD,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAA;QACvD,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,gCAAgC,CAAC,CAAA;QAC/D,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,2BAA2B,CAAC,CAAA;QAC1D,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAA;QACxC,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,eAAe,CAAC,CAAA;QAC9C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,OAAO,GAAG,oBAAoB,EAAE,CAAA;QACtC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACzC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;IAC3C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare function ottoVersion(): string;
|
|
2
|
+
export { MANIFEST, OPENCODE_CONFIG_DIR, KIMAKI_DATA_DIR } from "./manifest.js";
|
|
3
|
+
export { getInstalledVersion, detectPackage } from "./detect.js";
|
|
4
|
+
export type { InstalledPackage } from "./detect.js";
|
|
5
|
+
export { mergePlugins, readOttoConfig, writeOttoConfig, OTTO_DEFAULTS, buildSubagentThreadPolicy, mergeAgentPrompts, ensureSubagentThreadSkill, readOpenCodeConfig, readOpenCodeConfigState, writeOpenCodeConfig, ensureAgentMemoryConfig, } from "./config.js";
|
|
6
|
+
export type { OpenCodeConfig, OttoConfig, OttoSubagentThreads, OttoConfigReadStatus, OpenCodeConfigReadStatus } from "./config.js";
|
|
7
|
+
export { installPackage, upgradePackage, installMissingPackages, planStableUpgrades } from "./installer.js";
|
|
8
|
+
export type { UpgradeMode } from "./installer.js";
|
|
9
|
+
export { hasKimakiBinary, isKimakiRunning, restartKimaki } from "./lifecycle.js";
|
|
10
|
+
export { checkPackagePresence, checkConfigHealth, checkDirectoryHealth } from "./health.js";
|
|
11
|
+
export type { HealthResult, PackageCheck, ConfigHealth } from "./health.js";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC9E,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,EACL,YAAY,EACZ,cAAc,EACd,eAAe,EACf,aAAa,EACb,yBAAyB,EACzB,iBAAiB,EACjB,yBAAyB,EACzB,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AAClI,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAC3G,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAChF,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAC3F,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { MANIFEST } from "./manifest.js";
|
|
2
|
+
export function ottoVersion() {
|
|
3
|
+
return MANIFEST.version;
|
|
4
|
+
}
|
|
5
|
+
export { MANIFEST, OPENCODE_CONFIG_DIR, KIMAKI_DATA_DIR } from "./manifest.js";
|
|
6
|
+
export { getInstalledVersion, detectPackage } from "./detect.js";
|
|
7
|
+
export { mergePlugins, readOttoConfig, writeOttoConfig, OTTO_DEFAULTS, buildSubagentThreadPolicy, mergeAgentPrompts, ensureSubagentThreadSkill, readOpenCodeConfig, readOpenCodeConfigState, writeOpenCodeConfig, ensureAgentMemoryConfig, } from "./config.js";
|
|
8
|
+
export { installPackage, upgradePackage, installMissingPackages, planStableUpgrades } from "./installer.js";
|
|
9
|
+
export { hasKimakiBinary, isKimakiRunning, restartKimaki } from "./lifecycle.js";
|
|
10
|
+
export { checkPackagePresence, checkConfigHealth, checkDirectoryHealth } from "./health.js";
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAExC,MAAM,UAAU,WAAW;IACzB,OAAO,QAAQ,CAAC,OAAO,CAAA;AACzB,CAAC;AAED,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC9E,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhE,OAAO,EACL,YAAY,EACZ,cAAc,EACd,eAAe,EACf,aAAa,EACb,yBAAyB,EACzB,iBAAiB,EACjB,yBAAyB,EACzB,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAE3G,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAChF,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;IACpB,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type UpgradeMode = "stable" | "latest";
|
|
2
|
+
export declare function installPackage(name: string, version?: string): string;
|
|
3
|
+
export declare function upgradePackage(name: string, mode: UpgradeMode): string;
|
|
4
|
+
export declare function planStableUpgrades(packageNames: string[], getInstalled: (name: string) => string | null, pinned: Record<string, string>): {
|
|
5
|
+
name: string;
|
|
6
|
+
current: string | null;
|
|
7
|
+
target: string;
|
|
8
|
+
}[];
|
|
9
|
+
export declare function installMissingPackages(getInstalled: (name: string) => string | null, install?: (name: string, version?: string) => string): string[];
|
|
10
|
+
//# sourceMappingURL=installer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAE7C,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAOrE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,MAAM,CAStE;AAED,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,MAAM,EAAE,EACtB,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,EAC7C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,CAa5D;AAED,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,EAC7C,OAAO,GAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,MAAuB,GACnE,MAAM,EAAE,CAcV"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import { MANIFEST } from "./manifest.js";
|
|
3
|
+
export function installPackage(name, version) {
|
|
4
|
+
const spec = version ? `${name}@${version}` : name;
|
|
5
|
+
execSync(`npm install -g ${spec}`, {
|
|
6
|
+
encoding: "utf-8",
|
|
7
|
+
stdio: "pipe",
|
|
8
|
+
});
|
|
9
|
+
return spec;
|
|
10
|
+
}
|
|
11
|
+
export function upgradePackage(name, mode) {
|
|
12
|
+
if (mode === "stable") {
|
|
13
|
+
const pinned = MANIFEST.pinned[name];
|
|
14
|
+
if (!pinned) {
|
|
15
|
+
throw new Error(`No pinned version for ${name} in manifest`);
|
|
16
|
+
}
|
|
17
|
+
return installPackage(name, pinned);
|
|
18
|
+
}
|
|
19
|
+
return installPackage(name, "latest");
|
|
20
|
+
}
|
|
21
|
+
export function planStableUpgrades(packageNames, getInstalled, pinned) {
|
|
22
|
+
const upgrades = [];
|
|
23
|
+
for (const name of packageNames) {
|
|
24
|
+
const target = pinned[name];
|
|
25
|
+
if (!target) {
|
|
26
|
+
throw new Error(`No pinned version for ${name} in manifest`);
|
|
27
|
+
}
|
|
28
|
+
const current = getInstalled(name);
|
|
29
|
+
if (current !== target) {
|
|
30
|
+
upgrades.push({ name, current, target });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return upgrades;
|
|
34
|
+
}
|
|
35
|
+
export function installMissingPackages(getInstalled, install = installPackage) {
|
|
36
|
+
const installed = [];
|
|
37
|
+
for (const name of Object.keys(MANIFEST.packages)) {
|
|
38
|
+
const current = getInstalled(name);
|
|
39
|
+
if (!current) {
|
|
40
|
+
const pinned = MANIFEST.pinned[name];
|
|
41
|
+
if (!pinned) {
|
|
42
|
+
throw new Error(`No pinned version for ${name} in manifest`);
|
|
43
|
+
}
|
|
44
|
+
install(name, pinned);
|
|
45
|
+
installed.push(name);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return installed;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer.js","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAIxC,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,OAAgB;IAC3D,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;IAClD,QAAQ,CAAC,kBAAkB,IAAI,EAAE,EAAE;QACjC,QAAQ,EAAE,OAAO;QACjB,KAAK,EAAE,MAAM;KACd,CAAC,CAAA;IACF,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,IAAiB;IAC5D,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACpC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,cAAc,CAAC,CAAA;QAC9D,CAAC;QACD,OAAO,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IACrC,CAAC;IACD,OAAO,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;AACvC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,YAAsB,EACtB,YAA6C,EAC7C,MAA8B;IAE9B,MAAM,QAAQ,GAA+D,EAAE,CAAA;IAC/E,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAA;QAC3B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,cAAc,CAAC,CAAA;QAC9D,CAAC;QACD,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAA;QAClC,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;YACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAA;QAC1C,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,YAA6C,EAC7C,UAAsD,cAAc;IAEpE,MAAM,SAAS,GAAa,EAAE,CAAA;IAC9B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClD,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAA;QAClC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;YACpC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,cAAc,CAAC,CAAA;YAC9D,CAAC;YACD,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;YACrB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACtB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer.test.d.ts","sourceRoot":"","sources":["../src/installer.test.ts"],"names":[],"mappings":""}
|