mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-03 16:56:33 -04:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f299594633 | |||
| d925e34200 | |||
| 8df03aa1bc |
@@ -1502,25 +1502,18 @@ export interface ProjectCopyApi<E = never> {
|
||||
export type Endpoint25_0Input = {
|
||||
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
||||
}
|
||||
export type Endpoint25_0Output = { readonly location: Location.Info; readonly data: Vcs.Info }
|
||||
export type VcsGetOperation<E = never> = (input?: Endpoint25_0Input) => Effect.Effect<Endpoint25_0Output, E>
|
||||
export type Endpoint25_0Output = { readonly location: Location.Info; readonly data: ReadonlyArray<Vcs.FileStatus> }
|
||||
export type VcsStatusOperation<E = never> = (input?: Endpoint25_0Input) => Effect.Effect<Endpoint25_0Output, E>
|
||||
|
||||
export type Endpoint25_1Input = {
|
||||
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
||||
}
|
||||
export type Endpoint25_1Output = { readonly location: Location.Info; readonly data: ReadonlyArray<Vcs.FileStatus> }
|
||||
export type VcsStatusOperation<E = never> = (input?: Endpoint25_1Input) => Effect.Effect<Endpoint25_1Output, E>
|
||||
|
||||
export type Endpoint25_2Input = {
|
||||
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
||||
readonly mode: Vcs.Mode
|
||||
readonly context?: number | undefined
|
||||
}
|
||||
export type Endpoint25_2Output = { readonly location: Location.Info; readonly data: ReadonlyArray<FileDiff.Info> }
|
||||
export type VcsDiffOperation<E = never> = (input: Endpoint25_2Input) => Effect.Effect<Endpoint25_2Output, E>
|
||||
export type Endpoint25_1Output = { readonly location: Location.Info; readonly data: ReadonlyArray<FileDiff.Info> }
|
||||
export type VcsDiffOperation<E = never> = (input: Endpoint25_1Input) => Effect.Effect<Endpoint25_1Output, E>
|
||||
|
||||
export interface VcsApi<E = never> {
|
||||
readonly get: VcsGetOperation<E>
|
||||
readonly status: VcsStatusOperation<E>
|
||||
readonly diff: VcsDiffOperation<E>
|
||||
}
|
||||
|
||||
@@ -210,8 +210,6 @@ import type {
|
||||
Endpoint25_0Output,
|
||||
Endpoint25_1Input,
|
||||
Endpoint25_1Output,
|
||||
Endpoint25_2Input,
|
||||
Endpoint25_2Output,
|
||||
Endpoint26_0Output,
|
||||
Endpoint26_1Input,
|
||||
Endpoint26_1Output,
|
||||
@@ -1184,26 +1182,17 @@ const adaptGroup24 = (raw: RawClient["server.projectCopy"]) => ({
|
||||
|
||||
const Endpoint25_0 = (raw: RawClient["server.vcs"]) => (input?: Endpoint25_0Input) =>
|
||||
preserveEffect<Endpoint25_0Output>()(
|
||||
raw["vcs.get"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)),
|
||||
)
|
||||
|
||||
const Endpoint25_1 = (raw: RawClient["server.vcs"]) => (input?: Endpoint25_1Input) =>
|
||||
preserveEffect<Endpoint25_1Output>()(
|
||||
raw["vcs.status"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)),
|
||||
)
|
||||
|
||||
const Endpoint25_2 = (raw: RawClient["server.vcs"]) => (input: Endpoint25_2Input) =>
|
||||
preserveEffect<Endpoint25_2Output>()(
|
||||
const Endpoint25_1 = (raw: RawClient["server.vcs"]) => (input: Endpoint25_1Input) =>
|
||||
preserveEffect<Endpoint25_1Output>()(
|
||||
raw["vcs.diff"]({ query: { location: input["location"], mode: input["mode"], context: input["context"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
),
|
||||
)
|
||||
|
||||
const adaptGroup25 = (raw: RawClient["server.vcs"]) => ({
|
||||
get: Endpoint25_0(raw),
|
||||
status: Endpoint25_1(raw),
|
||||
diff: Endpoint25_2(raw),
|
||||
})
|
||||
const adaptGroup25 = (raw: RawClient["server.vcs"]) => ({ status: Endpoint25_0(raw), diff: Endpoint25_1(raw) })
|
||||
|
||||
const Endpoint26_0 = (raw: RawClient["server.debug"]) => () =>
|
||||
preserveEffect<Endpoint26_0Output>()(raw["debug.location"]({}).pipe(Effect.mapError(mapClientError)))
|
||||
|
||||
@@ -202,8 +202,6 @@ import type {
|
||||
ProjectCopyRemoveOutput,
|
||||
ProjectCopyRefreshInput,
|
||||
ProjectCopyRefreshOutput,
|
||||
VcsGetInput,
|
||||
VcsGetOutput,
|
||||
VcsStatusInput,
|
||||
VcsStatusOutput,
|
||||
VcsDiffInput,
|
||||
@@ -1704,18 +1702,6 @@ export function make(options: ClientOptions) {
|
||||
),
|
||||
},
|
||||
vcs: {
|
||||
get: (input?: VcsGetInput, requestOptions?: RequestOptions) =>
|
||||
request<VcsGetOutput>(
|
||||
{
|
||||
method: "GET",
|
||||
path: `/api/vcs`,
|
||||
query: { location: input?.["location"] },
|
||||
successStatus: 200,
|
||||
declaredStatuses: [401, 400],
|
||||
empty: false,
|
||||
},
|
||||
requestOptions,
|
||||
),
|
||||
status: (input?: VcsStatusInput, requestOptions?: RequestOptions) =>
|
||||
request<VcsStatusOutput>(
|
||||
{
|
||||
|
||||
@@ -530,8 +530,6 @@ export type ReferenceGitSource = {
|
||||
|
||||
export type ProjectCopyCopy = { directory: string }
|
||||
|
||||
export type VcsInfo = { branch?: string }
|
||||
|
||||
export type VcsFileStatus = {
|
||||
file: string
|
||||
additions: number
|
||||
@@ -4904,17 +4902,6 @@ export type ProjectCopyRefreshInput = {
|
||||
|
||||
export type ProjectCopyRefreshOutput = void
|
||||
|
||||
export type VcsGetInput = {
|
||||
readonly location?: {
|
||||
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
||||
}["location"]
|
||||
}
|
||||
|
||||
export type VcsGetOutput = {
|
||||
location: { directory: string; workspaceID?: string; project: { id: string; directory: string; canonical: string } }
|
||||
data: VcsInfo
|
||||
}
|
||||
|
||||
export type VcsStatusInput = {
|
||||
readonly location?: {
|
||||
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
||||
|
||||
@@ -61,7 +61,7 @@ const layer = Layer.effect(
|
||||
draft.default = id
|
||||
},
|
||||
update: (id, fn) => {
|
||||
const current = draft.agents.get(id) ?? (Info.empty(id) as Types.DeepMutable<Info>)
|
||||
const current = draft.agents.get(id) ?? (Info.default(id) as Types.DeepMutable<Info>)
|
||||
if (!draft.agents.has(id)) draft.agents.set(id, current)
|
||||
fn(current)
|
||||
current.id = id
|
||||
|
||||
@@ -58,7 +58,7 @@ export const Plugin = define({
|
||||
const files = yield* discover(fs, entry.path)
|
||||
return yield* Effect.forEach(files, (file) =>
|
||||
fs.readFileStringSafe(file.filepath).pipe(
|
||||
Effect.map((content) => content && decode(file, content)),
|
||||
Effect.map((content) => (content ? decode(file, content) : undefined)),
|
||||
Effect.catch(() => Effect.succeed(undefined)),
|
||||
),
|
||||
).pipe(
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
export * as Vcs from "./vcs"
|
||||
|
||||
import { Context, Effect, Layer, Ref, Stream } from "effect"
|
||||
import { Context, Effect, Layer } from "effect"
|
||||
import { FileDiff } from "@opencode-ai/schema/file-diff"
|
||||
import { FileSystem } from "@opencode-ai/schema/filesystem"
|
||||
import { FileStatus, Mode } from "@opencode-ai/schema/vcs"
|
||||
import { VcsEvent } from "@opencode-ai/schema/vcs-event"
|
||||
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
|
||||
import { FSUtil } from "@opencode-ai/util/fs-util"
|
||||
import { Location } from "./location"
|
||||
import { AppProcess } from "@opencode-ai/util/process"
|
||||
import { VcsGit } from "./vcs/git"
|
||||
import { VcsHg } from "./vcs/hg"
|
||||
import { Bus } from "./bus"
|
||||
|
||||
export { FileStatus, Mode }
|
||||
|
||||
@@ -20,7 +17,6 @@ export interface DiffOptions {
|
||||
}
|
||||
|
||||
export interface Interface {
|
||||
readonly branch: () => Effect.Effect<string | undefined>
|
||||
readonly status: () => Effect.Effect<FileStatus[]>
|
||||
readonly diff: (mode: Mode, options?: DiffOptions) => Effect.Effect<FileDiff.Info[]>
|
||||
}
|
||||
@@ -42,30 +38,8 @@ const layer = Layer.effect(
|
||||
const proc = yield* AppProcess.Service
|
||||
const fs = yield* FSUtil.Service
|
||||
const location = yield* Location.Service
|
||||
const bus = yield* Bus.Service
|
||||
const impl = adapter(proc, fs, location)
|
||||
const branch = yield* Ref.make(impl ? yield* impl.branch() : undefined)
|
||||
if (impl && location.vcs?.type === "git") {
|
||||
yield* bus.subscribe(FileSystem.Event.Changed).pipe(
|
||||
Stream.filter((event) => event.data.file.endsWith("HEAD")),
|
||||
Stream.runForEach(() =>
|
||||
Effect.gen(function* () {
|
||||
const next = yield* impl.branch()
|
||||
if (next === (yield* Ref.get(branch))) return
|
||||
yield* Ref.set(branch, next)
|
||||
yield* bus.publish(VcsEvent.BranchUpdated, { branch: next }, {
|
||||
location: { directory: location.directory, workspaceID: location.workspaceID },
|
||||
})
|
||||
}),
|
||||
),
|
||||
Effect.forkScoped({ startImmediately: true }),
|
||||
)
|
||||
}
|
||||
return Service.of({
|
||||
branch: Effect.fn("Vcs.branch")(function* () {
|
||||
if (!impl) return
|
||||
return yield* impl.branch()
|
||||
}),
|
||||
status: Effect.fn("Vcs.status")(function* () {
|
||||
if (!impl) return []
|
||||
return yield* impl.status()
|
||||
@@ -81,5 +55,5 @@ const layer = Layer.effect(
|
||||
export const node = makeLocationNode({
|
||||
service: Service,
|
||||
layer: layer,
|
||||
deps: [AppProcess.node, FSUtil.node, Location.node, Bus.node],
|
||||
deps: [AppProcess.node, FSUtil.node, Location.node],
|
||||
})
|
||||
|
||||
@@ -20,9 +20,6 @@ export function make(proc: AppProcess.Interface, input: { directory: string; wor
|
||||
const ctx: Ctx = { git: makeGit(proc), directory: input.directory, worktree: input.worktree }
|
||||
|
||||
return {
|
||||
branch: Effect.fn("VcsGit.branch")(function* () {
|
||||
return yield* ctx.git.branch(ctx.directory)
|
||||
}),
|
||||
status: Effect.fn("VcsGit.status")(function* () {
|
||||
const git = ctx.git
|
||||
const ref = (yield* git.hasHead(ctx.directory)) ? "HEAD" : undefined
|
||||
|
||||
@@ -73,9 +73,6 @@ export function make(
|
||||
})
|
||||
|
||||
return {
|
||||
branch: Effect.fn("VcsHg.branch")(function* () {
|
||||
return yield* hg.branch()
|
||||
}),
|
||||
status: Effect.fn("VcsHg.status")(function* () {
|
||||
const [items, batch] = yield* Effect.all(
|
||||
// Zero-context patches are enough to count changed lines.
|
||||
|
||||
@@ -120,7 +120,7 @@ describe("Agent", () => {
|
||||
const id = Agent.ID.make("custom")
|
||||
|
||||
yield* agent.transform((editor) => editor.update(id, () => {}))
|
||||
expect(yield* agent.get(id)).toEqual(Agent.Info.empty(id))
|
||||
expect(yield* agent.get(id)).toEqual(Agent.Info.default(id))
|
||||
|
||||
yield* agent.transform((editor) => editor.remove(id))
|
||||
expect(yield* agent.get(id)).toBeUndefined()
|
||||
|
||||
@@ -266,6 +266,7 @@ permissions:
|
||||
Use native v2 fields.`,
|
||||
)
|
||||
await fs.writeFile(path.join(tmp.path, "agents", "disabled.md"), "---\ndisabled: true\n---\nDisabled")
|
||||
await fs.writeFile(path.join(tmp.path, "agents", "empty.md"), "")
|
||||
await fs.writeFile(path.join(tmp.path, "modes", "plan.md"), "Make a plan.")
|
||||
})
|
||||
const agents = yield* Agent.Service
|
||||
@@ -295,6 +296,7 @@ Use native v2 fields.`,
|
||||
permissions: [...defaultPermissions, { action: "edit", resource: "*", effect: "deny" }],
|
||||
})
|
||||
expect(yield* agents.get(Agent.ID.make("disabled"))).toBeUndefined()
|
||||
expect(yield* agents.get(Agent.ID.make("empty"))).toBeUndefined()
|
||||
expect(yield* agents.get(Agent.ID.make("plan"))).toMatchObject({ system: "Make a plan.", mode: "primary" })
|
||||
}),
|
||||
),
|
||||
|
||||
@@ -12,7 +12,7 @@ import { readInitial, readUpdate } from "./lib/instructions"
|
||||
const build = Agent.ID.make("build")
|
||||
|
||||
const selection = (permissions: Permission.Ruleset = []) => {
|
||||
const info = Agent.Info.make({ ...Agent.Info.empty(build), permissions })
|
||||
const info = Agent.Info.make({ ...Agent.Info.default(build), permissions })
|
||||
return { id: info.id, info }
|
||||
}
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ test("Core reuses the canonical shared schemas", async () => {
|
||||
]
|
||||
for (const [core, shared] of schemas) expect(core).toBe(shared)
|
||||
|
||||
expect(Agent.Info.empty(Agent.ID.make("test"))).toEqual(Agent.Info.empty(Agent.ID.make("test")))
|
||||
expect(Agent.Info.default(Agent.ID.make("test"))).toEqual(Agent.Info.default(Agent.ID.make("test")))
|
||||
expect(coreModel.Info.default(coreProvider.ID.make("test"), coreModel.ID.make("model"))).toEqual(
|
||||
Model.Info.default(Provider.ID.make("test"), Model.ID.make("model")),
|
||||
)
|
||||
|
||||
@@ -47,7 +47,7 @@ const layer = (list: () => Skill.Info[]) =>
|
||||
describe("SkillInstructions", () => {
|
||||
it.effect("renders described agent skills and updates the complete available list", () => {
|
||||
const agent = Agent.Info.make({
|
||||
...Agent.Info.empty(build),
|
||||
...Agent.Info.default(build),
|
||||
permissions: [{ action: "skill", resource: "denied", effect: "deny" }],
|
||||
})
|
||||
let skills = [hidden, denied, manual, effect]
|
||||
@@ -80,7 +80,7 @@ describe("SkillInstructions", () => {
|
||||
})
|
||||
|
||||
it.effect("announces added and removed skills as deltas without restating the list", () => {
|
||||
const agent = Agent.Info.make(Agent.Info.empty(build))
|
||||
const agent = Agent.Info.make(Agent.Info.default(build))
|
||||
const debugging = Skill.Info.make({
|
||||
id: Skill.ID.make("debugging"),
|
||||
name: Skill.Name.make("Debugging"),
|
||||
@@ -117,7 +117,7 @@ describe("SkillInstructions", () => {
|
||||
})
|
||||
|
||||
it.effect("restates the full skill list when a description changes", () => {
|
||||
const agent = Agent.Info.make(Agent.Info.empty(build))
|
||||
const agent = Agent.Info.make(Agent.Info.default(build))
|
||||
let skills = [effect]
|
||||
return Effect.gen(function* () {
|
||||
const instructions = yield* SkillInstructions.Service
|
||||
@@ -138,7 +138,7 @@ describe("SkillInstructions", () => {
|
||||
|
||||
it.effect("omits instructions when the selected agent denies all skills", () => {
|
||||
const agent = Agent.Info.make({
|
||||
...Agent.Info.empty(build),
|
||||
...Agent.Info.default(build),
|
||||
permissions: [{ action: "skill", resource: "*", effect: "deny" }],
|
||||
})
|
||||
return Effect.gen(function* () {
|
||||
@@ -149,7 +149,7 @@ describe("SkillInstructions", () => {
|
||||
|
||||
it.effect("omits instructions when a resource-specific denial follows the global denial", () => {
|
||||
const agent = Agent.Info.make({
|
||||
...Agent.Info.empty(build),
|
||||
...Agent.Info.default(build),
|
||||
permissions: [
|
||||
{ action: "skill", resource: "*", effect: "deny" },
|
||||
{ action: "skill", resource: "hidden", effect: "deny" },
|
||||
@@ -163,7 +163,7 @@ describe("SkillInstructions", () => {
|
||||
|
||||
it.effect("retains specifically allowed skills after a global denial", () => {
|
||||
const agent = Agent.Info.make({
|
||||
...Agent.Info.empty(build),
|
||||
...Agent.Info.default(build),
|
||||
permissions: [
|
||||
{ action: "skill", resource: "*", effect: "deny" },
|
||||
{ action: "skill", resource: "effect", effect: "allow" },
|
||||
@@ -179,7 +179,7 @@ describe("SkillInstructions", () => {
|
||||
|
||||
it.effect("omits instructions when a specifically allowed skill is denied again", () => {
|
||||
const agent = Agent.Info.make({
|
||||
...Agent.Info.empty(build),
|
||||
...Agent.Info.default(build),
|
||||
permissions: [
|
||||
{ action: "skill", resource: "*", effect: "deny" },
|
||||
{ action: "skill", resource: "effect", effect: "allow" },
|
||||
|
||||
@@ -53,7 +53,6 @@ describe("Vcs", () => {
|
||||
withTmp((directory) =>
|
||||
Effect.gen(function* () {
|
||||
const vcs = yield* Vcs.Service
|
||||
expect(yield* vcs.branch()).toBeUndefined()
|
||||
expect(yield* vcs.status()).toEqual([])
|
||||
expect(yield* vcs.diff("working")).toEqual([])
|
||||
expect(yield* vcs.diff("branch")).toEqual([])
|
||||
@@ -156,7 +155,6 @@ describe("Vcs", () => {
|
||||
await commitAll(directory, "initial")
|
||||
})
|
||||
const vcs = yield* Vcs.Service
|
||||
expect(yield* vcs.branch()).toBe("main")
|
||||
expect(yield* vcs.diff("branch")).toEqual([])
|
||||
|
||||
yield* Effect.promise(async () => {
|
||||
@@ -164,7 +162,6 @@ describe("Vcs", () => {
|
||||
await fs.writeFile(path.join(directory, "file.txt"), "one\ntwo\n")
|
||||
await commitAll(directory, "feature change")
|
||||
})
|
||||
expect(yield* vcs.branch()).toBe("feature")
|
||||
const diff = yield* vcs.diff("branch")
|
||||
expect(diff.map((item) => ({ file: item.file, status: item.status }))).toEqual([
|
||||
{ file: "file.txt", status: "modified" },
|
||||
|
||||
@@ -19,7 +19,6 @@ import type {
|
||||
SessionPendingInfo,
|
||||
ShellInfo,
|
||||
SkillInfo,
|
||||
VcsInfo,
|
||||
} from "@opencode-ai/client"
|
||||
import type { ResolvedTheme } from "@opencode-ai/theme/tui"
|
||||
import type { CliRenderer, KeyEvent, Renderable } from "@opentui/core"
|
||||
@@ -114,11 +113,6 @@ export interface Data {
|
||||
default(): LocationRef
|
||||
sync(location?: LocationRef): Promise<void>
|
||||
invalidate(location?: LocationRef): void
|
||||
readonly vcs: {
|
||||
get(location?: LocationRef): VcsInfo | undefined
|
||||
sync(location?: LocationRef): Promise<void>
|
||||
invalidate(location?: LocationRef): void
|
||||
}
|
||||
readonly agent: LocationCollection<AgentInfo>
|
||||
readonly command: LocationCollection<CommandInfo>
|
||||
readonly integration: LocationCollection<IntegrationInfo>
|
||||
|
||||
@@ -13,20 +13,6 @@ const DiffQuery = Schema.Struct({
|
||||
})
|
||||
|
||||
export const VcsGroup = HttpApiGroup.make("server.vcs")
|
||||
.add(
|
||||
HttpApiEndpoint.get("vcs.get", "/api/vcs", {
|
||||
query: LocationQuery,
|
||||
success: Location.response(Vcs.Info),
|
||||
})
|
||||
.annotateMerge(locationQueryOpenApi)
|
||||
.annotateMerge(
|
||||
OpenApi.annotations({
|
||||
identifier: "v2.vcs.get",
|
||||
summary: "VCS information",
|
||||
description: "Get version control information for the requested location.",
|
||||
}),
|
||||
),
|
||||
)
|
||||
.add(
|
||||
HttpApiEndpoint.get("vcs.status", "/api/vcs/status", {
|
||||
query: LocationQuery,
|
||||
|
||||
@@ -36,7 +36,7 @@ export const Info = Schema.Struct({
|
||||
.annotate({ identifier: "Agent.Info" })
|
||||
.pipe(
|
||||
statics(() => ({
|
||||
empty: (id: ID) =>
|
||||
default: (id: ID) =>
|
||||
({
|
||||
id,
|
||||
name: Name.make(id),
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
export * as Vcs from "./vcs.js"
|
||||
|
||||
import { Schema } from "effect"
|
||||
import { NonNegativeInt, optional } from "./schema.js"
|
||||
|
||||
export const Info = Schema.Struct({
|
||||
branch: optional(Schema.String),
|
||||
}).annotate({ identifier: "Vcs.Info" })
|
||||
export interface Info extends Schema.Schema.Type<typeof Info> {}
|
||||
import { NonNegativeInt } from "./schema.js"
|
||||
|
||||
export const Mode = Schema.Literals(["working", "branch"]).annotate({ identifier: "Vcs.Mode" })
|
||||
export type Mode = typeof Mode.Type
|
||||
|
||||
@@ -7,14 +7,6 @@ import { response } from "../location"
|
||||
export const VcsHandler = HttpApiBuilder.group(Api, "server.vcs", (handlers) =>
|
||||
Effect.gen(function* () {
|
||||
return handlers
|
||||
.handle("vcs.get", () =>
|
||||
response(
|
||||
Effect.gen(function* () {
|
||||
const vcs = yield* Vcs.Service
|
||||
return { branch: yield* vcs.branch() }
|
||||
}),
|
||||
),
|
||||
)
|
||||
.handle("vcs.status", () =>
|
||||
response(
|
||||
Effect.gen(function* () {
|
||||
|
||||
@@ -1330,16 +1330,11 @@ export function Prompt(props: PromptProps) {
|
||||
if (!props.sessionID) {
|
||||
// No session yet: show where the next session will be created.
|
||||
const directory = currentLocation.ref?.directory ?? data.location.default().directory
|
||||
const branch = data.location.vcs.get(currentLocation.ref)?.branch
|
||||
const label = abbreviateHome(directory, paths.home)
|
||||
return branch ? label + ":" + branch : label
|
||||
return abbreviateHome(directory, paths.home)
|
||||
}
|
||||
if (status() !== "idle") return
|
||||
const ref = data.session.get(props.sessionID)?.location
|
||||
if (!ref) return
|
||||
const label = abbreviateHome(ref.directory, paths.home)
|
||||
const branch = data.location.vcs.get(ref)?.branch
|
||||
return branch ? label + ":" + branch : label
|
||||
const directory = data.session.get(props.sessionID)?.location.directory
|
||||
return directory ? abbreviateHome(directory, paths.home) : undefined
|
||||
})
|
||||
|
||||
const spinnerDef = createMemo(() => {
|
||||
|
||||
@@ -28,7 +28,6 @@ import type {
|
||||
ShellInfo,
|
||||
SkillInfo,
|
||||
OpenCodeEvent,
|
||||
VcsInfo,
|
||||
WebSearchProvider,
|
||||
} from "@opencode-ai/client"
|
||||
import type { Plugin } from "@opencode-ai/plugin/tui"
|
||||
@@ -50,7 +49,6 @@ type ShellWithLocation = ShellInfo & { readonly location: LocationRef }
|
||||
|
||||
type LocationData = {
|
||||
info?: LocationGetOutput
|
||||
vcs?: VcsInfo
|
||||
agent?: AgentInfo[]
|
||||
command?: CommandInfo[]
|
||||
integration?: IntegrationInfo[]
|
||||
@@ -907,15 +905,6 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
||||
result.location.mcp.resource.invalidate(event.location)
|
||||
void result.location.mcp.resource.sync(event.location)
|
||||
break
|
||||
case "vcs.branch.updated": {
|
||||
const ref = event.location ?? defaultLocation()
|
||||
const key = locationKey(ref)
|
||||
setStore("location", key, {
|
||||
...store.location[key],
|
||||
vcs: { branch: event.data.branch },
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1150,26 +1139,6 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
||||
default() {
|
||||
return defaultLocation()
|
||||
},
|
||||
vcs: {
|
||||
get(ref?: LocationRef) {
|
||||
return store.location[locationKey(ref ?? defaultLocation())]?.vcs
|
||||
},
|
||||
sync(ref?: LocationRef) {
|
||||
const location = ref ?? defaultLocation()
|
||||
const id = locationKey(location)
|
||||
return sync.run(`location.vcs:${id}`, async () => {
|
||||
const response = await client.api.vcs.get({ location: locationQuery(location) })
|
||||
const key = locationKey(response.location)
|
||||
setStore("location", key, {
|
||||
...store.location[key],
|
||||
vcs: response.data,
|
||||
})
|
||||
})
|
||||
},
|
||||
invalidate(ref?: LocationRef) {
|
||||
sync.invalidate(`location.vcs:${locationKey(ref ?? defaultLocation())}`)
|
||||
},
|
||||
},
|
||||
async sync(ref?: LocationRef) {
|
||||
const current = ref ?? defaultLocation()
|
||||
await sync.run(`location:${locationKey(current)}`, async () => {
|
||||
@@ -1192,7 +1161,6 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
||||
result.location.provider.sync(location),
|
||||
result.location.reference.sync(location),
|
||||
result.location.skill.sync(location),
|
||||
result.location.vcs.sync(location),
|
||||
result.shell.sync(location),
|
||||
result.session.form.sync("global", location),
|
||||
])
|
||||
@@ -1209,7 +1177,6 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
||||
result.location.provider.invalidate(location)
|
||||
result.location.reference.invalidate(location)
|
||||
result.location.skill.invalidate(location)
|
||||
result.location.vcs.invalidate(location)
|
||||
result.shell.invalidate(location)
|
||||
result.session.form.invalidate("global", location)
|
||||
},
|
||||
|
||||
@@ -6,14 +6,8 @@ function View(props: { context: Plugin.Context }) {
|
||||
const directory = createMemo(() =>
|
||||
props.context.location ? props.context.ui.format.path(props.context.location.directory) : undefined,
|
||||
)
|
||||
const value = createMemo(() => {
|
||||
const path = directory()
|
||||
if (!path) return
|
||||
const branch = props.context.data.location.vcs.get(props.context.location)?.branch
|
||||
return branch ? path + ":" + branch : path
|
||||
})
|
||||
return (
|
||||
<Show when={value()}>
|
||||
<Show when={directory()}>
|
||||
{(value) => <FilePath value={value()} maxWidth={38} fg={props.context.theme.text.subdued} />}
|
||||
</Show>
|
||||
)
|
||||
|
||||
@@ -127,11 +127,6 @@ export function createFetch(override?: FetchHandler, events?: ReturnType<typeof
|
||||
})
|
||||
if (url.pathname === "/api/reference")
|
||||
return json({ location: { directory, project: { id: "proj_test", directory, canonical: directory } }, data: [] })
|
||||
if (url.pathname === "/api/vcs")
|
||||
return json({
|
||||
location: { directory, project: { id: "proj_test", directory: worktree, canonical: worktree } },
|
||||
data: { branch: "main" },
|
||||
})
|
||||
if (url.pathname === "/api/websearch/provider") {
|
||||
return json({ location: { directory, project: { id: "proj_test", directory, canonical: directory } }, data: [] })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user