fix: address Cubic CLI and agent issues — URL encode, JSONC leading comments, config clone, untracked files, parse error handling, cache path, message-dir dedup
This commit is contained in:
parent
5ca3d9c489
commit
d6fbe7bd8d
@ -1,3 +1,6 @@
|
|||||||
|
import { join } from "node:path"
|
||||||
|
|
||||||
|
import { getOpenCodeCacheDir } from "../../../shared"
|
||||||
import type { AvailableModelsInfo, ModelResolutionInfo, OmoConfig } from "./model-resolution-types"
|
import type { AvailableModelsInfo, ModelResolutionInfo, OmoConfig } from "./model-resolution-types"
|
||||||
import { formatModelWithVariant, getCategoryEffectiveVariant, getEffectiveVariant } from "./model-resolution-variant"
|
import { formatModelWithVariant, getCategoryEffectiveVariant, getEffectiveVariant } from "./model-resolution-variant"
|
||||||
|
|
||||||
@ -7,6 +10,7 @@ export function buildModelResolutionDetails(options: {
|
|||||||
config: OmoConfig
|
config: OmoConfig
|
||||||
}): string[] {
|
}): string[] {
|
||||||
const details: string[] = []
|
const details: string[] = []
|
||||||
|
const cacheFile = join(getOpenCodeCacheDir(), "models.json")
|
||||||
|
|
||||||
details.push("═══ Available Models (from cache) ═══")
|
details.push("═══ Available Models (from cache) ═══")
|
||||||
details.push("")
|
details.push("")
|
||||||
@ -16,7 +20,7 @@ export function buildModelResolutionDetails(options: {
|
|||||||
` Sample: ${options.available.providers.slice(0, 6).join(", ")}${options.available.providers.length > 6 ? "..." : ""}`
|
` Sample: ${options.available.providers.slice(0, 6).join(", ")}${options.available.providers.length > 6 ? "..." : ""}`
|
||||||
)
|
)
|
||||||
details.push(` Total models: ${options.available.modelCount}`)
|
details.push(` Total models: ${options.available.modelCount}`)
|
||||||
details.push(` Cache: ~/.cache/opencode/models.json`)
|
details.push(` Cache: ${cacheFile}`)
|
||||||
details.push(` ℹ Runtime: only connected providers used`)
|
details.push(` ℹ Runtime: only connected providers used`)
|
||||||
details.push(` Refresh: opencode models --refresh`)
|
details.push(` Refresh: opencode models --refresh`)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -1,18 +1 @@
|
|||||||
import { existsSync, readdirSync } from "node:fs"
|
export { getMessageDir } from "./message-storage-locator"
|
||||||
import { join } from "node:path"
|
|
||||||
|
|
||||||
import { MESSAGE_STORAGE } from "../hook-message-injector"
|
|
||||||
|
|
||||||
export function getMessageDir(sessionID: string): string | null {
|
|
||||||
if (!existsSync(MESSAGE_STORAGE)) return null
|
|
||||||
|
|
||||||
const directPath = join(MESSAGE_STORAGE, sessionID)
|
|
||||||
if (existsSync(directPath)) return directPath
|
|
||||||
|
|
||||||
for (const dir of readdirSync(MESSAGE_STORAGE)) {
|
|
||||||
const sessionPath = join(MESSAGE_STORAGE, dir, sessionID)
|
|
||||||
if (existsSync(sessionPath)) return sessionPath
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|||||||
@ -15,7 +15,11 @@ const execFileSyncMock = mock((file: string, args: string[], _opts: { cwd?: stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (subcommand === "status") {
|
if (subcommand === "status") {
|
||||||
return " M file.ts\n"
|
return " M file.ts\n?? new-file.ts\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subcommand === "ls-files") {
|
||||||
|
return "new-file.ts\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(`unexpected args: ${args.join(" ")}`)
|
throw new Error(`unexpected args: ${args.join(" ")}`)
|
||||||
@ -38,7 +42,7 @@ describe("collectGitDiffStats", () => {
|
|||||||
|
|
||||||
//#then
|
//#then
|
||||||
expect(execSyncMock).not.toHaveBeenCalled()
|
expect(execSyncMock).not.toHaveBeenCalled()
|
||||||
expect(execFileSyncMock).toHaveBeenCalledTimes(2)
|
expect(execFileSyncMock).toHaveBeenCalledTimes(3)
|
||||||
|
|
||||||
const [firstCallFile, firstCallArgs, firstCallOpts] = execFileSyncMock.mock
|
const [firstCallFile, firstCallArgs, firstCallOpts] = execFileSyncMock.mock
|
||||||
.calls[0]! as unknown as [string, string[], { cwd?: string }]
|
.calls[0]! as unknown as [string, string[], { cwd?: string }]
|
||||||
@ -54,6 +58,13 @@ describe("collectGitDiffStats", () => {
|
|||||||
expect(secondCallOpts.cwd).toBe(directory)
|
expect(secondCallOpts.cwd).toBe(directory)
|
||||||
expect(secondCallArgs.join(" ")).not.toContain(directory)
|
expect(secondCallArgs.join(" ")).not.toContain(directory)
|
||||||
|
|
||||||
|
const [thirdCallFile, thirdCallArgs, thirdCallOpts] = execFileSyncMock.mock
|
||||||
|
.calls[2]! as unknown as [string, string[], { cwd?: string }]
|
||||||
|
expect(thirdCallFile).toBe("git")
|
||||||
|
expect(thirdCallArgs).toEqual(["ls-files", "--others", "--exclude-standard"])
|
||||||
|
expect(thirdCallOpts.cwd).toBe(directory)
|
||||||
|
expect(thirdCallArgs.join(" ")).not.toContain(directory)
|
||||||
|
|
||||||
expect(result).toEqual([
|
expect(result).toEqual([
|
||||||
{
|
{
|
||||||
path: "file.ts",
|
path: "file.ts",
|
||||||
@ -61,6 +72,12 @@ describe("collectGitDiffStats", () => {
|
|||||||
removed: 2,
|
removed: 2,
|
||||||
status: "modified",
|
status: "modified",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "new-file.ts",
|
||||||
|
added: 0,
|
||||||
|
removed: 0,
|
||||||
|
status: "added",
|
||||||
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -12,8 +12,6 @@ export function collectGitDiffStats(directory: string): GitFileStat[] {
|
|||||||
stdio: ["pipe", "pipe", "pipe"],
|
stdio: ["pipe", "pipe", "pipe"],
|
||||||
}).trim()
|
}).trim()
|
||||||
|
|
||||||
if (!diffOutput) return []
|
|
||||||
|
|
||||||
const statusOutput = execFileSync("git", ["status", "--porcelain"], {
|
const statusOutput = execFileSync("git", ["status", "--porcelain"], {
|
||||||
cwd: directory,
|
cwd: directory,
|
||||||
encoding: "utf-8",
|
encoding: "utf-8",
|
||||||
@ -21,8 +19,27 @@ export function collectGitDiffStats(directory: string): GitFileStat[] {
|
|||||||
stdio: ["pipe", "pipe", "pipe"],
|
stdio: ["pipe", "pipe", "pipe"],
|
||||||
}).trim()
|
}).trim()
|
||||||
|
|
||||||
|
const untrackedOutput = execFileSync("git", ["ls-files", "--others", "--exclude-standard"], {
|
||||||
|
cwd: directory,
|
||||||
|
encoding: "utf-8",
|
||||||
|
timeout: 5000,
|
||||||
|
stdio: ["pipe", "pipe", "pipe"],
|
||||||
|
}).trim()
|
||||||
|
|
||||||
|
const untrackedNumstat = untrackedOutput
|
||||||
|
? untrackedOutput
|
||||||
|
.split("\n")
|
||||||
|
.filter(Boolean)
|
||||||
|
.map((filePath) => `0\t0\t${filePath}`)
|
||||||
|
.join("\n")
|
||||||
|
: ""
|
||||||
|
|
||||||
|
const combinedNumstat = [diffOutput, untrackedNumstat].filter(Boolean).join("\n").trim()
|
||||||
|
|
||||||
|
if (!combinedNumstat) return []
|
||||||
|
|
||||||
const statusMap = parseGitStatusPorcelain(statusOutput)
|
const statusMap = parseGitStatusPorcelain(statusOutput)
|
||||||
return parseGitDiffNumstat(diffOutput, statusMap)
|
return parseGitDiffNumstat(combinedNumstat, statusMap)
|
||||||
} catch {
|
} catch {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user