opencode-context-tree 0.1.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/CHANGELOG.md +84 -0
- package/LICENSE +21 -0
- package/README.md +122 -0
- package/dist/server.js +19792 -0
- package/dist/tui.js +22742 -0
- package/docs/USAGE.md +155 -0
- package/package.json +93 -0
- package/src/core/actions.ts +53 -0
- package/src/core/adopt.ts +93 -0
- package/src/core/consumers.ts +39 -0
- package/src/core/crop.ts +176 -0
- package/src/core/cropplan.ts +201 -0
- package/src/core/ctree-args.ts +89 -0
- package/src/core/decision.ts +97 -0
- package/src/core/journal.ts +343 -0
- package/src/core/lanes.ts +149 -0
- package/src/core/navigation.ts +95 -0
- package/src/core/tokens.ts +105 -0
- package/src/core/transcript.ts +124 -0
- package/src/core/tree.ts +738 -0
- package/src/core/undo.ts +52 -0
- package/src/server/index.ts +278 -0
- package/src/shared/adopt.ts +82 -0
- package/src/shared/debug.ts +9 -0
- package/src/shared/store.ts +286 -0
- package/src/tui/actions.ts +447 -0
- package/src/tui/editor.ts +45 -0
- package/src/tui/index.tsx +421 -0
- package/src/tui/route.tsx +1058 -0
- package/src/tui/transcripts.ts +55 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapters from OpenCode's live message/part shapes (api.state, SDK) to core's
|
|
3
|
+
* `Transcript`, plus a small async loader for sessions other than the current one.
|
|
4
|
+
*/
|
|
5
|
+
import type { TuiPluginApi } from "@opencode-ai/plugin/tui"
|
|
6
|
+
import type { StepPart, Transcript, TranscriptMessage } from "../core/transcript.js"
|
|
7
|
+
|
|
8
|
+
type AnyMessage = { id: string; role: string; time: { created: number; completed?: number }; tokens?: TranscriptMessage["tokens"]; summary?: unknown }
|
|
9
|
+
type AnyPart = { id: string; type: string; text?: string; tool?: string; callID?: string; state?: StepPart["state"]; time?: StepPart["time"]; metadata?: Record<string, unknown> }
|
|
10
|
+
|
|
11
|
+
export function toStepPart(p: AnyPart): StepPart {
|
|
12
|
+
return { id: p.id, type: p.type, text: p.text, tool: p.tool, callID: p.callID, state: p.state, time: p.time, metadata: p.metadata }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function toTranscriptMessage(m: AnyMessage, parts: readonly AnyPart[]): TranscriptMessage {
|
|
16
|
+
return {
|
|
17
|
+
id: m.id,
|
|
18
|
+
role: m.role === "user" ? "user" : "assistant",
|
|
19
|
+
time: m.time,
|
|
20
|
+
tokens: m.tokens,
|
|
21
|
+
summary: m.role === "assistant" && m.summary === true ? true : undefined,
|
|
22
|
+
parts: parts.map(toStepPart),
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Reactive transcript of the session the TUI has loaded (api.state is a Solid store). */
|
|
27
|
+
export function liveTranscript(api: TuiPluginApi, sessionID: string): Transcript {
|
|
28
|
+
const messages = api.state.session.messages(sessionID) as unknown as readonly AnyMessage[]
|
|
29
|
+
const title = api.state.session.get(sessionID)?.title ?? sessionID
|
|
30
|
+
return {
|
|
31
|
+
sessionID,
|
|
32
|
+
title,
|
|
33
|
+
status: "available",
|
|
34
|
+
messages: messages.map((m) => toTranscriptMessage(m, api.state.part(m.id) as unknown as readonly AnyPart[])),
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** One-shot transcript of any session through the SDK. `limit` returns the *last* N and the
|
|
39
|
+
* `before` cursor is opaque (raw ids are rejected), so the whole session is fetched at once. */
|
|
40
|
+
export async function fetchTranscript(api: TuiPluginApi, sessionID: string, directory: string): Promise<Transcript> {
|
|
41
|
+
const session = await api.client.session.get({ sessionID, directory }).catch(() => undefined)
|
|
42
|
+
if (!session?.data) return { sessionID, title: sessionID, status: "deleted", messages: [] }
|
|
43
|
+
const res = await api.client.session.messages({ sessionID, directory })
|
|
44
|
+
const messages = ((res.data as unknown as { info: AnyMessage; parts: AnyPart[] }[] | undefined) ?? []).map((m) => toTranscriptMessage(m.info, m.parts))
|
|
45
|
+
return { sessionID, title: (session.data as { title?: string }).title ?? sessionID, status: "available", messages }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Context window of the model that answered last, for the gauge and the Input lane scale. */
|
|
49
|
+
export function modelContextLimit(api: TuiPluginApi, sessionID: string): number | undefined {
|
|
50
|
+
const last = [...(api.state.session.messages(sessionID) as unknown as { role: string; providerID?: string; modelID?: string }[])].reverse().find((m) => m.role === "assistant")
|
|
51
|
+
if (!last?.providerID || !last.modelID) return undefined
|
|
52
|
+
const provider = api.state.provider.find((p) => p.id === last.providerID)
|
|
53
|
+
const model = provider?.models[last.modelID] as { limit?: { context?: number } } | undefined
|
|
54
|
+
return model?.limit?.context
|
|
55
|
+
}
|