pluidr 0.7.0 → 0.7.2

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 (53) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +365 -365
  3. package/bin/pluidr.js +3 -3
  4. package/package.json +45 -45
  5. package/src/cli/commands/doctor.js +113 -101
  6. package/src/cli/commands/init.js +47 -43
  7. package/src/cli/commands/launch.js +46 -44
  8. package/src/cli/commands/uninstall.js +90 -63
  9. package/src/cli/commands/update.js +6 -6
  10. package/src/cli/index.js +57 -57
  11. package/src/cli/wizard/selectModelTier.js +40 -40
  12. package/src/core/agentPromptWriter.js +32 -32
  13. package/src/core/agentPromptWriter.test.js +56 -56
  14. package/src/core/backup.js +46 -40
  15. package/src/core/configBuilder.js +32 -32
  16. package/src/core/configBuilder.test.js +93 -93
  17. package/src/core/configWriter.js +10 -10
  18. package/src/core/identityHeader.js +8 -8
  19. package/src/core/paths.js +11 -9
  20. package/src/core/paths.test.js +29 -21
  21. package/src/core/pluginWriter.js +29 -29
  22. package/src/core/squeezeInstaller.js +158 -161
  23. package/src/core/squeezeInstaller.test.js +79 -75
  24. package/src/core/themeWriter.js +12 -0
  25. package/src/core/themeWriter.test.js +29 -0
  26. package/src/core/tuiConfigWriter.js +22 -0
  27. package/src/core/tuiConfigWriter.test.js +38 -0
  28. package/src/core/version.js +8 -8
  29. package/src/core/versionCheck.js +44 -35
  30. package/src/core/versionCheck.test.js +12 -2
  31. package/src/plugins/README.md +68 -68
  32. package/src/plugins/pluidr-squeeze.js +77 -77
  33. package/src/templates/agent-prompts/auditor.txt +20 -20
  34. package/src/templates/agent-prompts/coder.txt +87 -87
  35. package/src/templates/agent-prompts/compose-reporter.txt +55 -55
  36. package/src/templates/agent-prompts/composer.txt +429 -430
  37. package/src/templates/agent-prompts/debug-reporter.txt +65 -65
  38. package/src/templates/agent-prompts/debugger.txt +152 -151
  39. package/src/templates/agent-prompts/fixer.txt +66 -66
  40. package/src/templates/agent-prompts/hierarchy.txt +96 -96
  41. package/src/templates/agent-prompts/inspector.txt +79 -79
  42. package/src/templates/agent-prompts/patcher.txt +20 -20
  43. package/src/templates/agent-prompts/plan-checker.txt +45 -45
  44. package/src/templates/agent-prompts/plan-writer.txt +57 -57
  45. package/src/templates/agent-prompts/probe-reporter.txt +62 -62
  46. package/src/templates/agent-prompts/prober.txt +94 -90
  47. package/src/templates/agent-prompts/researcher.txt +48 -48
  48. package/src/templates/agent-prompts/reviewer.txt +57 -57
  49. package/src/templates/agent-prompts/tester.txt +66 -66
  50. package/src/templates/agent-prompts/tracer.txt +33 -33
  51. package/src/templates/model-defaults.json +73 -73
  52. package/src/templates/opencode.config.json +482 -481
  53. package/src/templates/themes/pluidr-contrast.json +177 -0
@@ -1,32 +1,32 @@
1
- import { readFileSync } from "node:fs"
2
- import { resolve } from "node:path"
3
-
4
- export function buildConfig(tierChoices, templatesDir) {
5
- const configPath = resolve(templatesDir, "opencode.config.json")
6
- const defaultsPath = resolve(templatesDir, "model-defaults.json")
7
-
8
- const config = JSON.parse(readFileSync(configPath, "utf-8"))
9
- const modelDefaults = JSON.parse(readFileSync(defaultsPath, "utf-8"))
10
-
11
- // Validate: every agent in model-defaults must have a key in config.agent
12
- const defaultedAgents = new Set(
13
- Object.values(modelDefaults).flatMap((tier) => tier.agents),
14
- )
15
- const missingAgents = [...defaultedAgents].filter(
16
- (name) => !(name in config.agent),
17
- )
18
- if (missingAgents.length > 0) {
19
- throw new Error(
20
- `Template validation failed: agent(s) not found in opencode.config.json: ${missingAgents.join(", ")}`,
21
- )
22
- }
23
-
24
- for (const [tierKey, tier] of Object.entries(modelDefaults)) {
25
- const model = tierChoices[tierKey]
26
- for (const agentName of tier.agents) {
27
- config.agent[agentName].model = model
28
- }
29
- }
30
-
31
- return config
32
- }
1
+ import { readFileSync } from "node:fs"
2
+ import { resolve } from "node:path"
3
+
4
+ export function buildConfig(tierChoices, templatesDir) {
5
+ const configPath = resolve(templatesDir, "opencode.config.json")
6
+ const defaultsPath = resolve(templatesDir, "model-defaults.json")
7
+
8
+ const config = JSON.parse(readFileSync(configPath, "utf-8"))
9
+ const modelDefaults = JSON.parse(readFileSync(defaultsPath, "utf-8"))
10
+
11
+ // Validate: every agent in model-defaults must have a key in config.agent
12
+ const defaultedAgents = new Set(
13
+ Object.values(modelDefaults).flatMap((tier) => tier.agents),
14
+ )
15
+ const missingAgents = [...defaultedAgents].filter(
16
+ (name) => !(name in config.agent),
17
+ )
18
+ if (missingAgents.length > 0) {
19
+ throw new Error(
20
+ `Template validation failed: agent(s) not found in opencode.config.json: ${missingAgents.join(", ")}`,
21
+ )
22
+ }
23
+
24
+ for (const [tierKey, tier] of Object.entries(modelDefaults)) {
25
+ const model = tierChoices[tierKey]
26
+ for (const agentName of tier.agents) {
27
+ config.agent[agentName].model = model
28
+ }
29
+ }
30
+
31
+ return config
32
+ }
@@ -1,93 +1,93 @@
1
- import { describe, it } from "node:test"
2
- import assert from "node:assert"
3
- import { mkdtempSync, writeFileSync, rmSync } from "node:fs"
4
- import { join } from "node:path"
5
- import { tmpdir } from "node:os"
6
- import { buildConfig } from "./configBuilder.js"
7
-
8
- describe("configBuilder", () => {
9
- it("injects models into agent config per tier", () => {
10
- const tmpDir = mkdtempSync(join(tmpdir(), "configbuilder-test-"))
11
-
12
- const configJson = {
13
- agent: {
14
- composer: {},
15
- reviewer: {},
16
- coder: {},
17
- },
18
- }
19
- const defaultsJson = {
20
- reasoning: {
21
- provider: "test",
22
- model: "big-model",
23
- agents: ["composer"],
24
- },
25
- precision: {
26
- provider: "test",
27
- model: "mid-model",
28
- agents: ["reviewer"],
29
- },
30
- fast: {
31
- provider: "test",
32
- model: "small-model",
33
- agents: ["coder"],
34
- },
35
- }
36
-
37
- writeFileSync(join(tmpDir, "opencode.config.json"), JSON.stringify(configJson), "utf-8")
38
- writeFileSync(join(tmpDir, "model-defaults.json"), JSON.stringify(defaultsJson), "utf-8")
39
-
40
- const result = buildConfig(
41
- {
42
- reasoning: "test/big-model",
43
- precision: "test/mid-model",
44
- fast: "test/small-model",
45
- },
46
- tmpDir,
47
- )
48
-
49
- assert.strictEqual(result.agent.composer.model, "test/big-model")
50
- assert.strictEqual(result.agent.reviewer.model, "test/mid-model")
51
- assert.strictEqual(result.agent.coder.model, "test/small-model")
52
-
53
- rmSync(tmpDir, { recursive: true })
54
- })
55
-
56
- it("throws an error if a defaulted agent is missing from config template", () => {
57
- const tmpDir = mkdtempSync(join(tmpdir(), "configbuilder-test-err-"))
58
-
59
- const configJson = {
60
- agent: {
61
- // missing 'composer'
62
- coder: {},
63
- },
64
- }
65
- const defaultsJson = {
66
- reasoning: {
67
- provider: "test",
68
- model: "big-model",
69
- agents: ["composer"],
70
- },
71
- fast: {
72
- provider: "test",
73
- model: "small-model",
74
- agents: ["coder"],
75
- },
76
- }
77
-
78
- writeFileSync(join(tmpDir, "opencode.config.json"), JSON.stringify(configJson), "utf-8")
79
- writeFileSync(join(tmpDir, "model-defaults.json"), JSON.stringify(defaultsJson), "utf-8")
80
-
81
- assert.throws(() => {
82
- buildConfig(
83
- {
84
- reasoning: "test/big-model",
85
- fast: "test/small-model",
86
- },
87
- tmpDir,
88
- )
89
- }, /Template validation failed: agent\(s\) not found/)
90
-
91
- rmSync(tmpDir, { recursive: true })
92
- })
93
- })
1
+ import { describe, it } from "node:test"
2
+ import assert from "node:assert"
3
+ import { mkdtempSync, writeFileSync, rmSync } from "node:fs"
4
+ import { join } from "node:path"
5
+ import { tmpdir } from "node:os"
6
+ import { buildConfig } from "./configBuilder.js"
7
+
8
+ describe("configBuilder", () => {
9
+ it("injects models into agent config per tier", () => {
10
+ const tmpDir = mkdtempSync(join(tmpdir(), "configbuilder-test-"))
11
+
12
+ const configJson = {
13
+ agent: {
14
+ composer: {},
15
+ reviewer: {},
16
+ coder: {},
17
+ },
18
+ }
19
+ const defaultsJson = {
20
+ reasoning: {
21
+ provider: "test",
22
+ model: "big-model",
23
+ agents: ["composer"],
24
+ },
25
+ precision: {
26
+ provider: "test",
27
+ model: "mid-model",
28
+ agents: ["reviewer"],
29
+ },
30
+ fast: {
31
+ provider: "test",
32
+ model: "small-model",
33
+ agents: ["coder"],
34
+ },
35
+ }
36
+
37
+ writeFileSync(join(tmpDir, "opencode.config.json"), JSON.stringify(configJson), "utf-8")
38
+ writeFileSync(join(tmpDir, "model-defaults.json"), JSON.stringify(defaultsJson), "utf-8")
39
+
40
+ const result = buildConfig(
41
+ {
42
+ reasoning: "test/big-model",
43
+ precision: "test/mid-model",
44
+ fast: "test/small-model",
45
+ },
46
+ tmpDir,
47
+ )
48
+
49
+ assert.strictEqual(result.agent.composer.model, "test/big-model")
50
+ assert.strictEqual(result.agent.reviewer.model, "test/mid-model")
51
+ assert.strictEqual(result.agent.coder.model, "test/small-model")
52
+
53
+ rmSync(tmpDir, { recursive: true })
54
+ })
55
+
56
+ it("throws an error if a defaulted agent is missing from config template", () => {
57
+ const tmpDir = mkdtempSync(join(tmpdir(), "configbuilder-test-err-"))
58
+
59
+ const configJson = {
60
+ agent: {
61
+ // missing 'composer'
62
+ coder: {},
63
+ },
64
+ }
65
+ const defaultsJson = {
66
+ reasoning: {
67
+ provider: "test",
68
+ model: "big-model",
69
+ agents: ["composer"],
70
+ },
71
+ fast: {
72
+ provider: "test",
73
+ model: "small-model",
74
+ agents: ["coder"],
75
+ },
76
+ }
77
+
78
+ writeFileSync(join(tmpDir, "opencode.config.json"), JSON.stringify(configJson), "utf-8")
79
+ writeFileSync(join(tmpDir, "model-defaults.json"), JSON.stringify(defaultsJson), "utf-8")
80
+
81
+ assert.throws(() => {
82
+ buildConfig(
83
+ {
84
+ reasoning: "test/big-model",
85
+ fast: "test/small-model",
86
+ },
87
+ tmpDir,
88
+ )
89
+ }, /Template validation failed: agent\(s\) not found/)
90
+
91
+ rmSync(tmpDir, { recursive: true })
92
+ })
93
+ })
@@ -1,10 +1,10 @@
1
- import { mkdirSync, writeFileSync } from "node:fs"
2
- import { join } from "node:path"
3
- import { getConfigDir } from "./paths.js"
4
-
5
- export function writeConfig(configObject, targetDir) {
6
- const baseDir = targetDir || getConfigDir()
7
- const configPath = join(baseDir, "opencode.jsonc")
8
- mkdirSync(baseDir, { recursive: true })
9
- writeFileSync(configPath, JSON.stringify(configObject, null, 2), "utf-8")
10
- }
1
+ import { mkdirSync, writeFileSync } from "node:fs"
2
+ import { join } from "node:path"
3
+ import { getConfigDir } from "./paths.js"
4
+
5
+ export function writeConfig(configObject, targetDir) {
6
+ const baseDir = targetDir || getConfigDir()
7
+ const configPath = join(baseDir, "opencode.jsonc")
8
+ mkdirSync(baseDir, { recursive: true })
9
+ writeFileSync(configPath, JSON.stringify(configObject, null, 2), "utf-8")
10
+ }
@@ -1,8 +1,8 @@
1
- // Single source of truth for the agent identity prefix prepended to every
2
- // generated prompt file. Mirrors the system identity concept from the
3
- // dropped hook-based AgentSelfIdentityPlugin, but as a static prepend
4
- // (KISS: agent names are known at install time).
5
-
6
- export default function IDENTITY_HEADER(agentName) {
7
- return `You are the "${agentName}" agent.\n\n`
8
- }
1
+ // Single source of truth for the agent identity prefix prepended to every
2
+ // generated prompt file. Mirrors the system identity concept from the
3
+ // dropped hook-based AgentSelfIdentityPlugin, but as a static prepend
4
+ // (KISS: agent names are known at install time).
5
+
6
+ export default function IDENTITY_HEADER(agentName) {
7
+ return `You are the "${agentName}" agent.\n\n`
8
+ }
package/src/core/paths.js CHANGED
@@ -1,9 +1,11 @@
1
- import { homedir } from "node:os"
2
- import { join } from "node:path"
3
-
4
- const BASE = join(homedir(), ".config", "opencode")
5
-
6
- export const getConfigDir = () => BASE
7
- export const getConfigPath = () => join(BASE, "opencode.jsonc")
8
- export const getPromptsDir = () => join(BASE, "prompts")
9
- // ponytail: getBackupPath removed (YAGNI)
1
+ import { homedir } from "node:os"
2
+ import { join } from "node:path"
3
+
4
+ const BASE = join(homedir(), ".config", "opencode")
5
+
6
+ export const getConfigDir = () => BASE
7
+ export const getConfigPath = () => join(BASE, "opencode.jsonc")
8
+ export const getTuiConfigPath = () => join(BASE, "tui.json")
9
+ export const getPromptsDir = () => join(BASE, "prompts")
10
+ export const getThemesDir = () => join(BASE, "themes")
11
+ // ponytail: getBackupPath removed (YAGNI)
@@ -1,21 +1,29 @@
1
- import { describe, it } from "node:test"
2
- import assert from "node:assert"
3
- import { homedir } from "node:os"
4
- import { join } from "node:path"
5
- import { getConfigDir, getConfigPath, getPromptsDir } from "./paths.js"
6
-
7
- const BASE = join(homedir(), ".config", "opencode")
8
-
9
- describe("paths", () => {
10
- it("getConfigDir returns ~/.config/opencode", () => {
11
- assert.strictEqual(getConfigDir(), BASE)
12
- })
13
-
14
- it("getConfigPath returns opencode.jsonc path", () => {
15
- assert.strictEqual(getConfigPath(), join(BASE, "opencode.jsonc"))
16
- })
17
-
18
- it("getPromptsDir returns prompts path", () => {
19
- assert.strictEqual(getPromptsDir(), join(BASE, "prompts"))
20
- })
21
- })
1
+ import { describe, it } from "node:test"
2
+ import assert from "node:assert"
3
+ import { homedir } from "node:os"
4
+ import { join } from "node:path"
5
+ import { getConfigDir, getConfigPath, getTuiConfigPath, getPromptsDir, getThemesDir } from "./paths.js"
6
+
7
+ const BASE = join(homedir(), ".config", "opencode")
8
+
9
+ describe("paths", () => {
10
+ it("getConfigDir returns ~/.config/opencode", () => {
11
+ assert.strictEqual(getConfigDir(), BASE)
12
+ })
13
+
14
+ it("getConfigPath returns opencode.jsonc path", () => {
15
+ assert.strictEqual(getConfigPath(), join(BASE, "opencode.jsonc"))
16
+ })
17
+
18
+ it("getTuiConfigPath returns tui.json path", () => {
19
+ assert.strictEqual(getTuiConfigPath(), join(BASE, "tui.json"))
20
+ })
21
+
22
+ it("getPromptsDir returns prompts path", () => {
23
+ assert.strictEqual(getPromptsDir(), join(BASE, "prompts"))
24
+ })
25
+
26
+ it("getThemesDir returns themes path", () => {
27
+ assert.strictEqual(getThemesDir(), join(BASE, "themes"))
28
+ })
29
+ })
@@ -1,29 +1,29 @@
1
- import { copyFileSync, existsSync, mkdirSync, writeFileSync } from "node:fs"
2
- import { dirname, join, resolve } from "node:path"
3
- import { fileURLToPath } from "node:url"
4
- import { getConfigDir } from "./paths.js"
5
-
6
- const __dirname = dirname(fileURLToPath(import.meta.url))
7
- const PLUGINS = ["pluidr-flow.js", "pluidr-squeeze.js"]
8
- const PACKAGE_JSON = {
9
- type: "module",
10
- dependencies: { "@opencode-ai/plugin": "^1.17.9" },
11
- }
12
-
13
- export function writePluginBundle(targetDir) {
14
- const baseDir = targetDir || getConfigDir()
15
- const pluginsDir = join(baseDir, "plugins")
16
- mkdirSync(pluginsDir, { recursive: true })
17
-
18
- for (const name of PLUGINS) {
19
- const sourcePath = resolve(__dirname, "../plugins", name)
20
- copyFileSync(sourcePath, join(pluginsDir, name))
21
- }
22
- }
23
-
24
- export function writePluginPackageJson(targetDir) {
25
- const baseDir = targetDir || getConfigDir()
26
- const packageJsonPath = join(baseDir, "package.json")
27
-
28
- writeFileSync(packageJsonPath, JSON.stringify(PACKAGE_JSON, null, 2), "utf-8")
29
- }
1
+ import { copyFileSync, existsSync, mkdirSync, writeFileSync } from "node:fs"
2
+ import { dirname, join, resolve } from "node:path"
3
+ import { fileURLToPath } from "node:url"
4
+ import { getConfigDir } from "./paths.js"
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url))
7
+ const PLUGINS = ["pluidr-flow.js", "pluidr-squeeze.js"]
8
+ const PACKAGE_JSON = {
9
+ type: "module",
10
+ dependencies: { "@opencode-ai/plugin": "^1.17.9" },
11
+ }
12
+
13
+ export function writePluginBundle(targetDir) {
14
+ const baseDir = targetDir || getConfigDir()
15
+ const pluginsDir = join(baseDir, "plugins")
16
+ mkdirSync(pluginsDir, { recursive: true })
17
+
18
+ for (const name of PLUGINS) {
19
+ const sourcePath = resolve(__dirname, "../plugins", name)
20
+ copyFileSync(sourcePath, join(pluginsDir, name))
21
+ }
22
+ }
23
+
24
+ export function writePluginPackageJson(targetDir) {
25
+ const baseDir = targetDir || getConfigDir()
26
+ const packageJsonPath = join(baseDir, "package.json")
27
+
28
+ writeFileSync(packageJsonPath, JSON.stringify(PACKAGE_JSON, null, 2), "utf-8")
29
+ }