Skip to content

Commit 05d5d8d

Browse files
authored
Merge pull request #101 from Tarquinen/chore/simplify-version-updates
Remove autoUpdate feature and simplify version checking
2 parents 9f54923 + baeb946 commit 05d5d8d

File tree

4 files changed

+26
-121
lines changed

4 files changed

+26
-121
lines changed

README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
Automatically reduces token usage in OpenCode by removing obsolete tool outputs from conversation history.
66

7-
![DCP in action](dcp-demo3.png)
7+
![DCP in action](dcp-demo.png)
88

99
## Installation
1010

@@ -13,7 +13,7 @@ Add to your OpenCode config:
1313
```jsonc
1414
// opencode.jsonc
1515
{
16-
"plugin": ["@tarquinen/opencode-dcp"],
16+
"plugin": ["@tarquinen/opencode-dcp@0.4.2"],
1717
"experimental": {
1818
"primary_tools": ["prune"]
1919
}
@@ -22,7 +22,9 @@ Add to your OpenCode config:
2222

2323
The `experimental.primary_tools` setting ensures the `prune` tool is only available to the primary agent (not subagents).
2424

25-
DCP automatically checks for new versions in the background. You'll see a toast notification when an update is available. To enable automatic background updates, set `"autoUpdate": true` in your DCP config.
25+
When a new version is available, DCP will show a toast notification. Update by changing the version number in your config.
26+
27+
> **Note:** Using `@latest` (e.g. `@tarquinen/opencode-dcp@latest`) does not reliably force the latest update in Opencode. Please use specific version numbers (e.g. `@0.4.2`).
2628
2729
Restart OpenCode. The plugin will automatically start optimizing your sessions.
2830

@@ -63,15 +65,14 @@ DCP uses its own config file (`~/.config/opencode/dcp.jsonc` or `.opencode/dcp.j
6365
| `model` | (session) | Model for analysis (e.g., `"anthropic/claude-haiku-4-5"`) |
6466
| `showModelErrorToasts` | `true` | Show notifications on model fallback |
6567
| `showUpdateToasts` | `true` | Show notifications when a new version is available |
66-
| `autoUpdate` | `false` | Automatically download new versions (restart to apply) |
6768
| `strictModelSelection` | `false` | Only run AI analysis with session or configured model (disables fallback models) |
6869
| `pruning_summary` | `"detailed"` | `"off"`, `"minimal"`, or `"detailed"` |
6970
| `nudge_freq` | `10` | How often to remind AI to prune (lower = more frequent) |
70-
| `protectedTools` | `["task", "todowrite", "todoread", "prune", "batch", "edit", "write"]` | Tools that are never pruned |
71+
| `protectedTools` | `["task", "todowrite", "todoread", "prune"]` | Tools that are never pruned |
7172
| `strategies.onIdle` | `["ai-analysis"]` | Strategies for automatic pruning |
7273
| `strategies.onTool` | `["ai-analysis"]` | Strategies when AI calls `prune` |
7374

74-
**Strategies:** `"ai-analysis"` uses LLM to identify prunable outputs. Empty array disables that trigger. Deduplication always runs automatically. More strategies coming soon.
75+
**Strategies:** `"ai-analysis"` uses LLM to identify prunable outputs. Empty array disables that trigger. Deduplication runs automatically on every request.
7576

7677
```jsonc
7778
{
@@ -80,7 +81,7 @@ DCP uses its own config file (`~/.config/opencode/dcp.jsonc` or `.opencode/dcp.j
8081
"onIdle": ["ai-analysis"],
8182
"onTool": ["ai-analysis"]
8283
},
83-
"protectedTools": ["task", "todowrite", "todoread", "prune", "batch", "edit", "write"]
84+
"protectedTools": ["task", "todowrite", "todoread", "prune"]
8485
}
8586
```
8687

index.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,7 @@ const plugin: Plugin = (async (ctx) => {
5353

5454
// Check for updates after a delay
5555
setTimeout(() => {
56-
checkForUpdates(ctx.client, logger, {
57-
showToast: config.showUpdateToasts ?? true,
58-
autoUpdate: config.autoUpdate ?? false
59-
}).catch(() => { })
56+
checkForUpdates(ctx.client, logger, config.showUpdateToasts ?? true).catch(() => { })
6057
}, 5000)
6158

6259
// Show migration toast if there were config migrations

lib/config.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ export interface PluginConfig {
1414
model?: string
1515
showModelErrorToasts?: boolean
1616
showUpdateToasts?: boolean
17-
autoUpdate?: boolean
1817
strictModelSelection?: boolean
1918
pruning_summary: "off" | "minimal" | "detailed"
2019
nudge_freq: number
@@ -32,10 +31,9 @@ export interface ConfigResult {
3231
const defaultConfig: PluginConfig = {
3332
enabled: true,
3433
debug: false,
35-
protectedTools: ['task', 'todowrite', 'todoread', 'prune', 'batch', 'edit', 'write'],
34+
protectedTools: ['task', 'todowrite', 'todoread', 'prune', 'batch'],
3635
showModelErrorToasts: true,
3736
showUpdateToasts: true,
38-
autoUpdate: false,
3937
strictModelSelection: false,
4038
pruning_summary: 'detailed',
4139
nudge_freq: 10,
@@ -52,7 +50,6 @@ const VALID_CONFIG_KEYS = new Set([
5250
'model',
5351
'showModelErrorToasts',
5452
'showUpdateToasts',
55-
'autoUpdate',
5653
'strictModelSelection',
5754
'pruning_summary',
5855
'nudge_freq',
@@ -118,8 +115,6 @@ function createDefaultConfig(): void {
118115
"showModelErrorToasts": true,
119116
// Show toast notifications when a new version is available
120117
"showUpdateToasts": true,
121-
// Automatically update to new versions (restart required to apply)
122-
"autoUpdate": false,
123118
// Only run AI analysis with session model or configured model (disables fallback models)
124119
"strictModelSelection": false,
125120
// AI analysis strategies (deduplication runs automatically on every request)
@@ -210,7 +205,6 @@ export function getConfig(ctx?: PluginInput): ConfigResult {
210205
model: globalConfig.model ?? config.model,
211206
showModelErrorToasts: globalConfig.showModelErrorToasts ?? config.showModelErrorToasts,
212207
showUpdateToasts: globalConfig.showUpdateToasts ?? config.showUpdateToasts,
213-
autoUpdate: globalConfig.autoUpdate ?? config.autoUpdate,
214208
strictModelSelection: globalConfig.strictModelSelection ?? config.strictModelSelection,
215209
strategies: mergeStrategies(config.strategies, globalConfig.strategies as any),
216210
pruning_summary: globalConfig.pruning_summary ?? config.pruning_summary,
@@ -243,7 +237,6 @@ export function getConfig(ctx?: PluginInput): ConfigResult {
243237
model: projectConfig.model ?? config.model,
244238
showModelErrorToasts: projectConfig.showModelErrorToasts ?? config.showModelErrorToasts,
245239
showUpdateToasts: projectConfig.showUpdateToasts ?? config.showUpdateToasts,
246-
autoUpdate: projectConfig.autoUpdate ?? config.autoUpdate,
247240
strictModelSelection: projectConfig.strictModelSelection ?? config.strictModelSelection,
248241
strategies: mergeStrategies(config.strategies, projectConfig.strategies as any),
249242
pruning_summary: projectConfig.pruning_summary ?? config.pruning_summary,

lib/version-checker.ts

Lines changed: 16 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import { readFileSync, writeFileSync, existsSync } from 'fs'
1+
import { readFileSync } from 'fs'
22
import { join, dirname } from 'path'
33
import { fileURLToPath } from 'url'
4-
import { homedir } from 'os'
54

65
export const PACKAGE_NAME = '@tarquinen/opencode-dcp'
76
export const NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`
@@ -11,20 +10,9 @@ const __dirname = dirname(__filename)
1110

1211
export function getLocalVersion(): string {
1312
try {
14-
let dir = __dirname
15-
for (let i = 0; i < 5; i++) {
16-
const pkgPath = join(dir, 'package.json')
17-
try {
18-
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'))
19-
if (pkg.name === PACKAGE_NAME) {
20-
return pkg.version
21-
}
22-
} catch {
23-
// Not found at this level, go up
24-
}
25-
dir = join(dir, '..')
26-
}
27-
return '0.0.0'
13+
const pkgPath = join(__dirname, '../../package.json')
14+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'))
15+
return pkg.version
2816
} catch {
2917
return '0.0.0'
3018
}
@@ -62,58 +50,7 @@ export function isOutdated(local: string, remote: string): boolean {
6250
return false
6351
}
6452

65-
/**
66-
* Updates config files to pin the new version.
67-
* Checks both global and local project configs.
68-
* Handles: "@tarquinen/opencode-dcp", "@tarquinen/opencode-dcp@latest", "@tarquinen/[email protected]"
69-
*/
70-
export function updateConfigVersion(newVersion: string, logger?: { info: (component: string, message: string, data?: any) => void }): boolean {
71-
const configs = [
72-
join(homedir(), '.config', 'opencode', 'opencode.jsonc'), // Global
73-
join(process.cwd(), '.opencode', 'opencode.jsonc') // Local project
74-
]
75-
76-
let anyUpdated = false
77-
78-
for (const configPath of configs) {
79-
try {
80-
if (!existsSync(configPath)) continue
81-
82-
const content = readFileSync(configPath, 'utf-8')
83-
84-
// Match @tarquinen/opencode-dcp with optional version suffix (latest, 1.2.3, etc)
85-
// The regex matches: " @tarquinen/opencode-dcp (optional @anything) "
86-
const regex = new RegExp(`"${PACKAGE_NAME}(@[^"]*)?"`,'g')
87-
const newEntry = `"${PACKAGE_NAME}@${newVersion}"`
88-
89-
if (!regex.test(content)) {
90-
continue
91-
}
92-
93-
// Reset regex state
94-
regex.lastIndex = 0
95-
const updatedContent = content.replace(regex, newEntry)
96-
97-
if (updatedContent !== content) {
98-
writeFileSync(configPath, updatedContent, 'utf-8')
99-
logger?.info("version", "Config updated", { configPath, newVersion })
100-
anyUpdated = true
101-
}
102-
} catch (err) {
103-
logger?.info("version", "Failed to update config", { configPath, error: (err as Error).message })
104-
}
105-
}
106-
107-
return anyUpdated
108-
}
109-
110-
export async function checkForUpdates(
111-
client: any,
112-
logger?: { info: (component: string, message: string, data?: any) => void },
113-
options: { showToast?: boolean; autoUpdate?: boolean } = {}
114-
): Promise<void> {
115-
const { showToast = true, autoUpdate = false } = options
116-
53+
export async function checkForUpdates(client: any, logger?: { info: (component: string, message: string, data?: any) => void }, showToast: boolean = true): Promise<void> {
11754
try {
11855
const local = getLocalVersion()
11956
const npm = await getNpmVersion()
@@ -128,43 +65,20 @@ export async function checkForUpdates(
12865
return
12966
}
13067

131-
logger?.info("version", "Update available", { local, npm, autoUpdate })
68+
logger?.info("version", "Update available", { local, npm })
13269

133-
if (autoUpdate) {
134-
// Attempt config update
135-
const updated = updateConfigVersion(npm, logger)
70+
if (!showToast) {
71+
return
72+
}
13673

137-
if (updated && showToast) {
138-
await client.tui.showToast({
139-
body: {
140-
title: "DCP: Updated!",
141-
message: `v${local} → v${npm}\nRestart OpenCode to apply`,
142-
variant: "success",
143-
duration: 6000
144-
}
145-
})
146-
} else if (!updated && showToast) {
147-
// Config update failed or plugin not found in config, show manual instructions
148-
await client.tui.showToast({
149-
body: {
150-
title: "DCP: Update available",
151-
message: `v${local} → v${npm}\nUpdate opencode.jsonc:\n"${PACKAGE_NAME}@${npm}"`,
152-
variant: "info",
153-
duration: 8000
154-
}
155-
})
74+
await client.tui.showToast({
75+
body: {
76+
title: "DCP: Update available",
77+
message: `v${local} → v${npm}\nUpdate opencode.jsonc: ${PACKAGE_NAME}@${npm}`,
78+
variant: "info",
79+
duration: 6000
15680
}
157-
} else if (showToast) {
158-
await client.tui.showToast({
159-
body: {
160-
title: "DCP: Update available",
161-
message: `v${local} → v${npm}\nUpdate opencode.jsonc:\n"${PACKAGE_NAME}@${npm}"`,
162-
variant: "info",
163-
duration: 8000
164-
}
165-
})
166-
}
81+
})
16782
} catch {
168-
// Silently fail version checks
16983
}
17084
}

0 commit comments

Comments
 (0)