@comfanion/workflow 4.38.3-dev.2 → 4.38.4-dev.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/package.json +1 -1
- package/src/build-info.json +4 -5
- package/src/opencode/config.yaml +0 -69
- package/src/opencode/gitignore +2 -0
- package/src/opencode/opencode.json +3 -5
- package/src/opencode/vectorizer.yaml +45 -0
- package/src/opencode/plugins/README.md +0 -182
- package/src/opencode/plugins/__tests__/custom-compaction.test.ts +0 -829
- package/src/opencode/plugins/__tests__/file-indexer.test.ts +0 -425
- package/src/opencode/plugins/__tests__/helpers/mock-ctx.ts +0 -171
- package/src/opencode/plugins/__tests__/leak-stress.test.ts +0 -315
- package/src/opencode/plugins/__tests__/usethis-todo.test.ts +0 -205
- package/src/opencode/plugins/__tests__/version-check.test.ts +0 -223
- package/src/opencode/plugins/custom-compaction.ts +0 -1080
- package/src/opencode/plugins/file-indexer.ts +0 -516
- package/src/opencode/plugins/usethis-todo-publish.ts +0 -44
- package/src/opencode/plugins/usethis-todo-ui.ts +0 -37
- package/src/opencode/plugins/version-check.ts +0 -230
- package/src/opencode/tools/codeindex.ts +0 -264
- package/src/opencode/tools/search.ts +0 -149
- package/src/opencode/tools/usethis_todo.ts +0 -538
- package/src/vectorizer/index.js +0 -573
- package/src/vectorizer/package.json +0 -16
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from "bun:test"
|
|
2
|
-
import { join } from "path"
|
|
3
|
-
import { writeFile } from "fs/promises"
|
|
4
|
-
import { VersionCheckPlugin } from "../version-check"
|
|
5
|
-
import { createMockCtx, createTempDir, cleanupTempDir } from "./helpers/mock-ctx"
|
|
6
|
-
|
|
7
|
-
// =============================================================================
|
|
8
|
-
// LOCAL REPLICAS of internal functions (not exported from plugin)
|
|
9
|
-
// These mirror the source logic so we can unit-test the algorithms directly.
|
|
10
|
-
// =============================================================================
|
|
11
|
-
|
|
12
|
-
/** Replica of compareVersions from version-check.ts (with pre-release strip fix) */
|
|
13
|
-
function compareVersions(local: string, latest: string): number {
|
|
14
|
-
const strip = (v: string) => v.replace(/-.*$/, '')
|
|
15
|
-
const localParts = strip(local).split('.').map(Number)
|
|
16
|
-
const latestParts = strip(latest).split('.').map(Number)
|
|
17
|
-
|
|
18
|
-
for (let i = 0; i < 3; i++) {
|
|
19
|
-
const l = localParts[i] || 0
|
|
20
|
-
const r = latestParts[i] || 0
|
|
21
|
-
if (l < r) return -1
|
|
22
|
-
if (l > r) return 1
|
|
23
|
-
}
|
|
24
|
-
return 0
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// =============================================================================
|
|
28
|
-
// UNIT TESTS: compareVersions (replica)
|
|
29
|
-
// =============================================================================
|
|
30
|
-
describe("compareVersions", () => {
|
|
31
|
-
it("returns 0 for equal versions", () => {
|
|
32
|
-
expect(compareVersions("1.0.0", "1.0.0")).toBe(0)
|
|
33
|
-
expect(compareVersions("4.36.21", "4.36.21")).toBe(0)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
it("returns -1 when local < latest (patch)", () => {
|
|
37
|
-
expect(compareVersions("1.0.0", "1.0.1")).toBe(-1)
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
it("returns -1 when local < latest (minor)", () => {
|
|
41
|
-
expect(compareVersions("1.0.0", "1.1.0")).toBe(-1)
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
it("returns -1 when local < latest (major)", () => {
|
|
45
|
-
expect(compareVersions("1.0.0", "2.0.0")).toBe(-1)
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
it("returns 1 when local > latest (patch)", () => {
|
|
49
|
-
expect(compareVersions("1.0.2", "1.0.1")).toBe(1)
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
it("returns 1 when local > latest (minor)", () => {
|
|
53
|
-
expect(compareVersions("1.2.0", "1.1.9")).toBe(1)
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
it("returns 1 when local > latest (major)", () => {
|
|
57
|
-
expect(compareVersions("3.0.0", "2.99.99")).toBe(1)
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
it("handles versions with missing parts", () => {
|
|
61
|
-
expect(compareVersions("1.0", "1.0.0")).toBe(0)
|
|
62
|
-
expect(compareVersions("1", "1.0.0")).toBe(0)
|
|
63
|
-
expect(compareVersions("1.0.0", "1.0")).toBe(0)
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
it("handles large version numbers", () => {
|
|
67
|
-
expect(compareVersions("100.200.300", "100.200.300")).toBe(0)
|
|
68
|
-
expect(compareVersions("100.200.300", "100.200.301")).toBe(-1)
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
it("handles pre-release versions (strips suffix)", () => {
|
|
72
|
-
expect(compareVersions("4.38.1-beta.1", "4.38.1")).toBe(0)
|
|
73
|
-
expect(compareVersions("4.38.1-dev.16", "4.38.2")).toBe(-1)
|
|
74
|
-
expect(compareVersions("5.0.0-rc.1", "4.99.99")).toBe(1)
|
|
75
|
-
expect(compareVersions("1.0.0-alpha", "1.0.0-beta")).toBe(0) // both strip to 1.0.0
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
it("does not return NaN for pre-release versions", () => {
|
|
79
|
-
const result = compareVersions("4.38.1-beta.1", "4.38.2")
|
|
80
|
-
expect(result).not.toBeNaN()
|
|
81
|
-
expect(result).toBe(-1)
|
|
82
|
-
})
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
// =============================================================================
|
|
86
|
-
// INTEGRATION: Plugin initialization & hooks
|
|
87
|
-
// =============================================================================
|
|
88
|
-
describe("VersionCheckPlugin", () => {
|
|
89
|
-
let tempDir: string
|
|
90
|
-
|
|
91
|
-
beforeEach(async () => {
|
|
92
|
-
tempDir = await createTempDir()
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
afterEach(async () => {
|
|
96
|
-
await cleanupTempDir(tempDir)
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
it("returns hooks object with event handler", async () => {
|
|
100
|
-
const ctx = createMockCtx(tempDir)
|
|
101
|
-
const hooks = await VersionCheckPlugin(ctx as any)
|
|
102
|
-
|
|
103
|
-
expect(hooks).toBeDefined()
|
|
104
|
-
expect(hooks.event).toBeFunction()
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
it("event handler is a no-op (does not throw)", async () => {
|
|
108
|
-
const ctx = createMockCtx(tempDir)
|
|
109
|
-
const hooks = await VersionCheckPlugin(ctx as any)
|
|
110
|
-
|
|
111
|
-
// Call event with various event types - should not throw
|
|
112
|
-
await hooks.event!({ event: { type: "session.idle" } as any })
|
|
113
|
-
await hooks.event!({ event: { type: "file.edited" } as any })
|
|
114
|
-
await hooks.event!({ event: { type: "unknown.event" } as any })
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
it("does not throw when client.tui is missing", async () => {
|
|
118
|
-
const ctx = {
|
|
119
|
-
directory: tempDir,
|
|
120
|
-
worktree: tempDir,
|
|
121
|
-
client: {},
|
|
122
|
-
project: { name: "test" },
|
|
123
|
-
serverUrl: new URL("http://localhost:3000"),
|
|
124
|
-
$: {},
|
|
125
|
-
}
|
|
126
|
-
// Should not throw even with minimal client
|
|
127
|
-
const hooks = await VersionCheckPlugin(ctx as any)
|
|
128
|
-
expect(hooks).toBeDefined()
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
it("getLocalVersion reads build-info.json via plugin behavior", async () => {
|
|
132
|
-
// Write build-info.json — the plugin reads this internally during setTimeout
|
|
133
|
-
await writeFile(
|
|
134
|
-
join(tempDir, ".opencode", "build-info.json"),
|
|
135
|
-
JSON.stringify({ version: "4.38.0" })
|
|
136
|
-
)
|
|
137
|
-
const ctx = createMockCtx(tempDir)
|
|
138
|
-
const hooks = await VersionCheckPlugin(ctx as any)
|
|
139
|
-
// Plugin initializes successfully
|
|
140
|
-
expect(hooks).toBeDefined()
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
it("getLocalVersion fallback to config.yaml", async () => {
|
|
144
|
-
await writeFile(
|
|
145
|
-
join(tempDir, ".opencode", "config.yaml"),
|
|
146
|
-
`version: "3.5.0"\nproject_name: test\n`
|
|
147
|
-
)
|
|
148
|
-
const ctx = createMockCtx(tempDir)
|
|
149
|
-
const hooks = await VersionCheckPlugin(ctx as any)
|
|
150
|
-
expect(hooks).toBeDefined()
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
it("getLanguage defaults to 'en' when config missing", async () => {
|
|
154
|
-
// No config.yaml — language detection should default to 'en'
|
|
155
|
-
const ctx = createMockCtx(tempDir)
|
|
156
|
-
const hooks = await VersionCheckPlugin(ctx as any)
|
|
157
|
-
expect(hooks).toBeDefined()
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
it("loads and saves cache via plugin lifecycle", async () => {
|
|
161
|
-
// Write version info so plugin has something to work with
|
|
162
|
-
await writeFile(
|
|
163
|
-
join(tempDir, ".opencode", "build-info.json"),
|
|
164
|
-
JSON.stringify({ version: "4.38.0" })
|
|
165
|
-
)
|
|
166
|
-
const ctx = createMockCtx(tempDir)
|
|
167
|
-
const hooks = await VersionCheckPlugin(ctx as any)
|
|
168
|
-
expect(hooks).toBeDefined()
|
|
169
|
-
// Plugin will attempt to check version in background (setTimeout)
|
|
170
|
-
// No assertion needed — just ensure no crash
|
|
171
|
-
})
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
// =============================================================================
|
|
175
|
-
// MEMORY SAFETY
|
|
176
|
-
// =============================================================================
|
|
177
|
-
describe("memory safety", () => {
|
|
178
|
-
let tempDir: string
|
|
179
|
-
|
|
180
|
-
beforeEach(async () => {
|
|
181
|
-
tempDir = await createTempDir()
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
afterEach(async () => {
|
|
185
|
-
await cleanupTempDir(tempDir)
|
|
186
|
-
})
|
|
187
|
-
|
|
188
|
-
it("no state accumulation across multiple event calls", async () => {
|
|
189
|
-
const ctx = createMockCtx(tempDir)
|
|
190
|
-
const hooks = await VersionCheckPlugin(ctx as any)
|
|
191
|
-
|
|
192
|
-
// Call event handler many times - should not accumulate state
|
|
193
|
-
for (let i = 0; i < 1000; i++) {
|
|
194
|
-
await hooks.event!({ event: { type: "session.idle" } as any })
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// If we get here without OOM or excessive delay, no leak
|
|
198
|
-
expect(true).toBe(true)
|
|
199
|
-
})
|
|
200
|
-
|
|
201
|
-
it("multiple plugin initializations don't leak", async () => {
|
|
202
|
-
const memBefore = process.memoryUsage().heapUsed
|
|
203
|
-
|
|
204
|
-
for (let i = 0; i < 50; i++) {
|
|
205
|
-
const dir = await createTempDir()
|
|
206
|
-
const ctx = createMockCtx(dir)
|
|
207
|
-
const hooks = await VersionCheckPlugin(ctx as any)
|
|
208
|
-
await hooks.event!({ event: { type: "session.idle" } as any })
|
|
209
|
-
await cleanupTempDir(dir)
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// Force GC if available
|
|
213
|
-
if (typeof Bun !== "undefined" && (globalThis as any).gc) {
|
|
214
|
-
;(globalThis as any).gc()
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const memAfter = process.memoryUsage().heapUsed
|
|
218
|
-
const growthMB = (memAfter - memBefore) / 1024 / 1024
|
|
219
|
-
|
|
220
|
-
// Memory growth should be < 50MB for 50 iterations
|
|
221
|
-
expect(growthMB).toBeLessThan(50)
|
|
222
|
-
})
|
|
223
|
-
})
|