saeeol 1.2.0 → 1.2.2
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 +14 -14
- package/src/cli/cmd/tui/component/dialog/dialog-agent.tsx +32 -0
- package/src/cli/cmd/tui/component/dialog/dialog-command.tsx +190 -0
- package/src/cli/cmd/tui/component/dialog/dialog-console-org.tsx +103 -0
- package/src/cli/cmd/tui/component/dialog/dialog-go-upsell.tsx +159 -0
- package/src/cli/cmd/tui/component/dialog/dialog-mcp.tsx +86 -0
- package/src/cli/cmd/tui/component/dialog/dialog-model.tsx +238 -0
- package/src/cli/cmd/tui/component/dialog/dialog-provider.tsx +343 -0
- package/src/cli/cmd/tui/component/dialog/dialog-session-delete-failed.tsx +103 -0
- package/src/cli/cmd/tui/component/dialog/dialog-session-list.tsx +301 -0
- package/src/cli/cmd/tui/component/dialog/dialog-session-rename.tsx +35 -0
- package/src/cli/cmd/tui/component/dialog/dialog-skill.tsx +37 -0
- package/src/cli/cmd/tui/component/dialog/dialog-stash.tsx +87 -0
- package/src/cli/cmd/tui/component/dialog/dialog-status.tsx +190 -0
- package/src/cli/cmd/tui/component/dialog/dialog-tag.tsx +44 -0
- package/src/cli/cmd/tui/component/dialog/dialog-theme-list.tsx +50 -0
- package/src/cli/cmd/tui/component/dialog/dialog-variant.tsx +39 -0
- package/src/cli/cmd/tui/component/dialog/dialog-workspace-create.tsx +200 -0
- package/src/cli/cmd/tui/component/dialog/dialog-workspace-unavailable.tsx +81 -0
- package/src/cli/cmd/tui/component/dialog-agent.tsx +1 -32
- package/src/cli/cmd/tui/component/dialog-command.tsx +1 -190
- package/src/cli/cmd/tui/component/dialog-console-org.tsx +1 -103
- package/src/cli/cmd/tui/component/dialog-go-upsell.tsx +1 -159
- package/src/cli/cmd/tui/component/dialog-mcp.tsx +1 -86
- package/src/cli/cmd/tui/component/dialog-model.tsx +1 -238
- package/src/cli/cmd/tui/component/dialog-provider.tsx +1 -343
- package/src/cli/cmd/tui/component/dialog-session-delete-failed.tsx +1 -103
- package/src/cli/cmd/tui/component/dialog-session-list.tsx +1 -301
- package/src/cli/cmd/tui/component/dialog-session-rename.tsx +1 -35
- package/src/cli/cmd/tui/component/dialog-skill.tsx +1 -37
- package/src/cli/cmd/tui/component/dialog-stash.tsx +1 -87
- package/src/cli/cmd/tui/component/dialog-status.tsx +1 -190
- package/src/cli/cmd/tui/component/dialog-tag.tsx +1 -44
- package/src/cli/cmd/tui/component/dialog-theme-list.tsx +1 -50
- package/src/cli/cmd/tui/component/dialog-variant.tsx +1 -39
- package/src/cli/cmd/tui/component/dialog-workspace-create.tsx +1 -200
- package/src/cli/cmd/tui/component/dialog-workspace-unavailable.tsx +1 -81
- package/src/session/compaction-helpers.ts +1 -169
- package/src/session/compaction.ts +1 -712
- package/src/session/core/compaction/compaction-helpers.ts +169 -0
- package/src/session/core/compaction/compaction.ts +712 -0
- package/src/session/core/compaction/overflow.ts +28 -0
- package/src/session/core/instruction.ts +234 -0
- package/src/session/core/llm.ts +504 -0
- package/src/session/core/network.ts +392 -0
- package/src/session/core/processor.ts +731 -0
- package/src/session/core/projectors.ts +139 -0
- package/src/session/core/resolve-tools.ts +241 -0
- package/src/session/core/retry.ts +149 -0
- package/src/session/core/revert.ts +173 -0
- package/src/session/core/run-state.ts +110 -0
- package/src/session/core/schema.ts +35 -0
- package/src/session/core/session-types.ts +160 -0
- package/src/session/core/session.sql.ts +124 -0
- package/src/session/core/session.ts +948 -0
- package/src/session/core/shell-exec.ts +205 -0
- package/src/session/core/status.ts +100 -0
- package/src/session/core/subtask.ts +268 -0
- package/src/session/core/summary.ts +173 -0
- package/src/session/core/system.ts +114 -0
- package/src/session/core/todo.ts +86 -0
- package/src/session/core/user-part.ts +293 -0
- package/src/session/instruction.ts +1 -234
- package/src/session/llm.ts +1 -504
- package/src/session/message/message-errors.ts +83 -0
- package/src/session/message/message-parts.ts +89 -0
- package/src/session/message/message-query.ts +107 -0
- package/src/session/message/message-transform.ts +156 -0
- package/src/session/message/message-types.ts +68 -0
- package/src/session/message/message-v2.ts +73 -0
- package/src/session/message/message.ts +192 -0
- package/src/session/message-errors.ts +1 -83
- package/src/session/message-parts.ts +1 -89
- package/src/session/message-query.ts +1 -107
- package/src/session/message-transform.ts +1 -156
- package/src/session/message-types.ts +1 -68
- package/src/session/message-v2.ts +1 -73
- package/src/session/message.ts +1 -192
- package/src/session/network.ts +1 -392
- package/src/session/overflow.ts +1 -28
- package/src/session/processor.ts +1 -731
- package/src/session/projectors.ts +2 -139
- package/src/session/prompt/prompt-command.ts +93 -0
- package/src/session/prompt/prompt-loop.ts +299 -0
- package/src/session/prompt/prompt-model.ts +44 -0
- package/src/session/prompt/prompt-reminders.ts +120 -0
- package/src/session/prompt/prompt-resolve.ts +42 -0
- package/src/session/prompt/prompt-schemas.ts +128 -0
- package/src/session/prompt/prompt-title.ts +55 -0
- package/src/session/prompt/prompt-types.ts +47 -0
- package/src/session/prompt/prompt-user-msg.ts +80 -0
- package/src/session/prompt/prompt.ts +211 -0
- package/src/session/prompt-command.ts +1 -93
- package/src/session/prompt-loop.ts +1 -299
- package/src/session/prompt-model.ts +1 -44
- package/src/session/prompt-reminders.ts +1 -120
- package/src/session/prompt-resolve.ts +1 -42
- package/src/session/prompt-schemas.ts +1 -128
- package/src/session/prompt-title.ts +1 -55
- package/src/session/prompt-types.ts +1 -47
- package/src/session/prompt-user-msg.ts +1 -80
- package/src/session/prompt.ts +1 -211
- package/src/session/resolve-tools.ts +1 -241
- package/src/session/retry.ts +1 -149
- package/src/session/revert.ts +1 -173
- package/src/session/run-state.ts +1 -110
- package/src/session/schema.ts +1 -35
- package/src/session/session-types.ts +1 -160
- package/src/session/session.sql.ts +1 -124
- package/src/session/session.ts +1 -948
- package/src/session/shell-exec.ts +1 -205
- package/src/session/status.ts +1 -100
- package/src/session/subtask.ts +1 -268
- package/src/session/summary.ts +1 -173
- package/src/session/system.ts +1 -114
- package/src/session/todo.ts +1 -86
- package/src/session/user-part.ts +1 -293
- package/src/tool/apply_patch.ts +1 -334
- package/src/tool/bash.ts +1 -656
- package/src/tool/core/external-directory.ts +55 -0
- package/src/tool/core/invalid.ts +21 -0
- package/src/tool/core/recall.ts +164 -0
- package/src/tool/core/recall.txt +12 -0
- package/src/tool/core/schema.ts +16 -0
- package/src/tool/core/tool.ts +162 -0
- package/src/tool/core/truncate.ts +160 -0
- package/src/tool/core/truncation-dir.ts +4 -0
- package/src/tool/diagnostics.ts +1 -20
- package/src/tool/edit-replacers.ts +1 -288
- package/src/tool/edit-utils.ts +1 -86
- package/src/tool/edit.ts +1 -262
- package/src/tool/external-directory.ts +1 -55
- package/src/tool/file/apply_patch.ts +334 -0
- package/src/tool/file/apply_patch.txt +33 -0
- package/src/tool/file/bash.ts +656 -0
- package/src/tool/file/bash.txt +119 -0
- package/src/tool/file/edit-replacers.ts +288 -0
- package/src/tool/file/edit-utils.ts +86 -0
- package/src/tool/file/edit.ts +262 -0
- package/src/tool/file/edit.txt +10 -0
- package/src/tool/file/read.ts +389 -0
- package/src/tool/file/read.txt +14 -0
- package/src/tool/file/write.ts +114 -0
- package/src/tool/file/write.txt +8 -0
- package/src/tool/glob.ts +1 -115
- package/src/tool/grep.ts +1 -151
- package/src/tool/integration/diagnostics.ts +20 -0
- package/src/tool/integration/lsp.ts +113 -0
- package/src/tool/integration/lsp.txt +24 -0
- package/src/tool/integration/mcp-exa.ts +73 -0
- package/src/tool/integration/package.ts +168 -0
- package/src/tool/integration/registry.ts +375 -0
- package/src/tool/invalid.ts +1 -21
- package/src/tool/lsp.ts +1 -113
- package/src/tool/mcp-exa.ts +1 -73
- package/src/tool/package.ts +1 -168
- package/src/tool/plan.ts +1 -30
- package/src/tool/question.ts +1 -52
- package/src/tool/read.ts +1 -389
- package/src/tool/recall.ts +1 -164
- package/src/tool/registry.ts +1 -375
- package/src/tool/schema.ts +1 -16
- package/src/tool/search/glob.ts +115 -0
- package/src/tool/search/glob.txt +6 -0
- package/src/tool/search/grep.ts +151 -0
- package/src/tool/search/grep.txt +8 -0
- package/src/tool/search/warpgrep.ts +107 -0
- package/src/tool/search/warpgrep.txt +10 -0
- package/src/tool/search/webfetch.ts +202 -0
- package/src/tool/search/webfetch.txt +13 -0
- package/src/tool/search/websearch.ts +71 -0
- package/src/tool/search/websearch.txt +14 -0
- package/src/tool/skill.ts +1 -91
- package/src/tool/task.ts +1 -197
- package/src/tool/todo.ts +1 -62
- package/src/tool/tool.ts +1 -162
- package/src/tool/truncate.ts +1 -160
- package/src/tool/truncation-dir.ts +1 -4
- package/src/tool/warpgrep.ts +1 -107
- package/src/tool/webfetch.ts +1 -202
- package/src/tool/websearch.ts +1 -71
- package/src/tool/workflow/plan-enter.txt +14 -0
- package/src/tool/workflow/plan-exit.txt +13 -0
- package/src/tool/workflow/plan.ts +30 -0
- package/src/tool/workflow/question.ts +52 -0
- package/src/tool/workflow/question.txt +11 -0
- package/src/tool/workflow/skill.ts +91 -0
- package/src/tool/workflow/skill.txt +5 -0
- package/src/tool/workflow/task.ts +197 -0
- package/src/tool/workflow/task.txt +57 -0
- package/src/tool/workflow/todo.ts +62 -0
- package/src/tool/workflow/todowrite.txt +167 -0
- package/src/tool/write.ts +1 -114
|
@@ -1,44 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { DialogSelect } from "@tui/ui/dialog-select"
|
|
3
|
-
import { useDialog } from "@tui/ui/dialog"
|
|
4
|
-
import { useSDK } from "@tui/context/sdk"
|
|
5
|
-
import { createStore } from "solid-js/store"
|
|
6
|
-
|
|
7
|
-
export function DialogTag(props: { onSelect?: (value: string) => void }) {
|
|
8
|
-
const sdk = useSDK()
|
|
9
|
-
const dialog = useDialog()
|
|
10
|
-
|
|
11
|
-
const [store] = createStore({
|
|
12
|
-
filter: "",
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
const [files] = createResource(
|
|
16
|
-
() => [store.filter],
|
|
17
|
-
async () => {
|
|
18
|
-
const result = await sdk.client.find.files({
|
|
19
|
-
query: store.filter,
|
|
20
|
-
})
|
|
21
|
-
if (result.error) return []
|
|
22
|
-
const sliced = (result.data ?? []).slice(0, 5)
|
|
23
|
-
return sliced
|
|
24
|
-
},
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
const options = createMemo(() =>
|
|
28
|
-
(files() ?? []).map((file) => ({
|
|
29
|
-
value: file,
|
|
30
|
-
title: file,
|
|
31
|
-
})),
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
<DialogSelect
|
|
36
|
-
title="Autocomplete"
|
|
37
|
-
options={options()}
|
|
38
|
-
onSelect={(option) => {
|
|
39
|
-
props.onSelect?.(option.value)
|
|
40
|
-
dialog.clear()
|
|
41
|
-
}}
|
|
42
|
-
/>
|
|
43
|
-
)
|
|
44
|
-
}
|
|
1
|
+
export * from "./dialog/dialog-tag"
|
|
@@ -1,50 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { useTheme } from "../context/theme"
|
|
3
|
-
import { useDialog } from "../ui/dialog"
|
|
4
|
-
import { onCleanup } from "solid-js"
|
|
5
|
-
|
|
6
|
-
export function DialogThemeList() {
|
|
7
|
-
const theme = useTheme()
|
|
8
|
-
const options = Object.keys(theme.all())
|
|
9
|
-
.sort((a, b) => a.localeCompare(b, undefined, { sensitivity: "base" }))
|
|
10
|
-
.map((value) => ({
|
|
11
|
-
title: value,
|
|
12
|
-
value: value,
|
|
13
|
-
}))
|
|
14
|
-
const dialog = useDialog()
|
|
15
|
-
let confirmed = false
|
|
16
|
-
let ref: DialogSelectRef<string>
|
|
17
|
-
const initial = theme.selected
|
|
18
|
-
|
|
19
|
-
onCleanup(() => {
|
|
20
|
-
if (!confirmed) theme.set(initial)
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<DialogSelect
|
|
25
|
-
title="Themes"
|
|
26
|
-
options={options}
|
|
27
|
-
current={initial}
|
|
28
|
-
onMove={(opt) => {
|
|
29
|
-
theme.set(opt.value)
|
|
30
|
-
}}
|
|
31
|
-
onSelect={(opt) => {
|
|
32
|
-
theme.set(opt.value)
|
|
33
|
-
confirmed = true
|
|
34
|
-
dialog.clear()
|
|
35
|
-
}}
|
|
36
|
-
ref={(r) => {
|
|
37
|
-
ref = r
|
|
38
|
-
}}
|
|
39
|
-
onFilter={(query) => {
|
|
40
|
-
if (query.length === 0) {
|
|
41
|
-
theme.set(initial)
|
|
42
|
-
return
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const first = ref.filtered[0]
|
|
46
|
-
if (first) theme.set(first.value)
|
|
47
|
-
}}
|
|
48
|
-
/>
|
|
49
|
-
)
|
|
50
|
-
}
|
|
1
|
+
export * from "./dialog/dialog-theme-list"
|
|
@@ -1,39 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { useLocal } from "@tui/context/local"
|
|
3
|
-
import { DialogSelect } from "@tui/ui/dialog-select"
|
|
4
|
-
import { useDialog } from "@tui/ui/dialog"
|
|
5
|
-
|
|
6
|
-
export function DialogVariant() {
|
|
7
|
-
const local = useLocal()
|
|
8
|
-
const dialog = useDialog()
|
|
9
|
-
|
|
10
|
-
const options = createMemo(() => {
|
|
11
|
-
return [
|
|
12
|
-
{
|
|
13
|
-
value: "default",
|
|
14
|
-
title: "Default",
|
|
15
|
-
onSelect: () => {
|
|
16
|
-
dialog.clear()
|
|
17
|
-
local.model.variant.set(undefined)
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
...local.model.variant.list().map((variant) => ({
|
|
21
|
-
value: variant,
|
|
22
|
-
title: variant,
|
|
23
|
-
onSelect: () => {
|
|
24
|
-
dialog.clear()
|
|
25
|
-
local.model.variant.set(variant)
|
|
26
|
-
},
|
|
27
|
-
})),
|
|
28
|
-
]
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
return (
|
|
32
|
-
<DialogSelect<string>
|
|
33
|
-
options={options()}
|
|
34
|
-
title={"Select variant"}
|
|
35
|
-
current={local.model.variant.selected()}
|
|
36
|
-
flat={true}
|
|
37
|
-
/>
|
|
38
|
-
)
|
|
39
|
-
}
|
|
1
|
+
export * from "./dialog/dialog-variant"
|
|
@@ -1,200 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { useDialog } from "@tui/ui/dialog"
|
|
3
|
-
import { DialogSelect } from "@tui/ui/dialog-select"
|
|
4
|
-
import { useRoute } from "@tui/context/route"
|
|
5
|
-
import { useSync } from "@tui/context/sync"
|
|
6
|
-
import { useProject } from "@tui/context/project"
|
|
7
|
-
import { createMemo, createSignal, onMount } from "solid-js"
|
|
8
|
-
import { setTimeout as sleep } from "node:timers/promises"
|
|
9
|
-
import { errorMessage } from "@/util/error"
|
|
10
|
-
import { useSDK } from "../context/sdk"
|
|
11
|
-
import { useToast } from "../ui/toast"
|
|
12
|
-
|
|
13
|
-
type Adapter = {
|
|
14
|
-
type: string
|
|
15
|
-
name: string
|
|
16
|
-
description: string
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function scoped(sdk: ReturnType<typeof useSDK>, sync: ReturnType<typeof useSync>, workspaceID: string) {
|
|
20
|
-
return createSaeeolClient({
|
|
21
|
-
baseUrl: sdk.url,
|
|
22
|
-
fetch: sdk.fetch,
|
|
23
|
-
directory: sync.path.directory || sdk.directory,
|
|
24
|
-
experimental_workspaceID: workspaceID,
|
|
25
|
-
})
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export async function openWorkspaceSession(input: {
|
|
29
|
-
dialog: ReturnType<typeof useDialog>
|
|
30
|
-
route: ReturnType<typeof useRoute>
|
|
31
|
-
sdk: ReturnType<typeof useSDK>
|
|
32
|
-
sync: ReturnType<typeof useSync>
|
|
33
|
-
toast: ReturnType<typeof useToast>
|
|
34
|
-
workspaceID: string
|
|
35
|
-
}) {
|
|
36
|
-
const client = scoped(input.sdk, input.sync, input.workspaceID)
|
|
37
|
-
|
|
38
|
-
while (true) {
|
|
39
|
-
const result = await client.session.create({ workspace: input.workspaceID }).catch(() => undefined)
|
|
40
|
-
if (!result) {
|
|
41
|
-
input.toast.show({
|
|
42
|
-
message: "Failed to create workspace session",
|
|
43
|
-
variant: "error",
|
|
44
|
-
})
|
|
45
|
-
return
|
|
46
|
-
}
|
|
47
|
-
if (result.response?.status && result.response.status >= 500 && result.response.status < 600) {
|
|
48
|
-
await sleep(1000)
|
|
49
|
-
continue
|
|
50
|
-
}
|
|
51
|
-
if (!result.data) {
|
|
52
|
-
input.toast.show({
|
|
53
|
-
message: "Failed to create workspace session",
|
|
54
|
-
variant: "error",
|
|
55
|
-
})
|
|
56
|
-
return
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
input.route.navigate({
|
|
60
|
-
type: "session",
|
|
61
|
-
sessionID: result.data.id,
|
|
62
|
-
})
|
|
63
|
-
input.dialog.clear()
|
|
64
|
-
return
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export async function restoreWorkspaceSession(input: {
|
|
69
|
-
dialog: ReturnType<typeof useDialog>
|
|
70
|
-
sdk: ReturnType<typeof useSDK>
|
|
71
|
-
sync: ReturnType<typeof useSync>
|
|
72
|
-
project: ReturnType<typeof useProject>
|
|
73
|
-
toast: ReturnType<typeof useToast>
|
|
74
|
-
workspaceID: string
|
|
75
|
-
sessionID: string
|
|
76
|
-
done?: () => void
|
|
77
|
-
}) {
|
|
78
|
-
const result = await input.sdk.client.experimental.workspace
|
|
79
|
-
.sessionRestore({ id: input.workspaceID, sessionID: input.sessionID })
|
|
80
|
-
.catch(() => undefined)
|
|
81
|
-
if (!result?.data) {
|
|
82
|
-
input.toast.show({
|
|
83
|
-
message: `Failed to restore session: ${errorMessage(result?.error ?? "no response")}`,
|
|
84
|
-
variant: "error",
|
|
85
|
-
})
|
|
86
|
-
return
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
input.project.workspace.set(input.workspaceID)
|
|
90
|
-
|
|
91
|
-
await input.sync.bootstrap({ fatal: false }).catch(() => undefined)
|
|
92
|
-
|
|
93
|
-
await Promise.all([input.project.workspace.sync(), input.sync.session.sync(input.sessionID)])
|
|
94
|
-
|
|
95
|
-
input.toast.show({
|
|
96
|
-
message: "Session restored into the new workspace",
|
|
97
|
-
variant: "success",
|
|
98
|
-
})
|
|
99
|
-
input.done?.()
|
|
100
|
-
if (input.done) return
|
|
101
|
-
input.dialog.clear()
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export function DialogWorkspaceCreate(props: { onSelect: (workspaceID: string) => Promise<void> | void }) {
|
|
105
|
-
const dialog = useDialog()
|
|
106
|
-
const sync = useSync()
|
|
107
|
-
const project = useProject()
|
|
108
|
-
const sdk = useSDK()
|
|
109
|
-
const toast = useToast()
|
|
110
|
-
const [creating, setCreating] = createSignal<string>()
|
|
111
|
-
const [adapters, setAdapters] = createSignal<Adapter[]>()
|
|
112
|
-
|
|
113
|
-
onMount(() => {
|
|
114
|
-
dialog.setSize("medium")
|
|
115
|
-
void (async () => {
|
|
116
|
-
const dir = sync.path.directory || sdk.directory
|
|
117
|
-
const url = new URL("/experimental/workspace/adapter", sdk.url)
|
|
118
|
-
if (dir) url.searchParams.set("directory", dir)
|
|
119
|
-
const res = await sdk
|
|
120
|
-
.fetch(url)
|
|
121
|
-
.then((x) => x.json() as Promise<Adapter[]>)
|
|
122
|
-
.catch(() => undefined)
|
|
123
|
-
if (!res) {
|
|
124
|
-
toast.show({
|
|
125
|
-
message: "Failed to load workspace adapters",
|
|
126
|
-
variant: "error",
|
|
127
|
-
})
|
|
128
|
-
return
|
|
129
|
-
}
|
|
130
|
-
setAdapters(res)
|
|
131
|
-
})()
|
|
132
|
-
})
|
|
133
|
-
|
|
134
|
-
const options = createMemo(() => {
|
|
135
|
-
const type = creating()
|
|
136
|
-
if (type) {
|
|
137
|
-
return [
|
|
138
|
-
{
|
|
139
|
-
title: `Creating ${type} workspace...`,
|
|
140
|
-
value: "creating" as const,
|
|
141
|
-
description: "This can take a while for remote environments",
|
|
142
|
-
},
|
|
143
|
-
]
|
|
144
|
-
}
|
|
145
|
-
const list = adapters()
|
|
146
|
-
if (!list) {
|
|
147
|
-
return [
|
|
148
|
-
{
|
|
149
|
-
title: "Loading workspaces...",
|
|
150
|
-
value: "loading" as const,
|
|
151
|
-
description: "Fetching available workspace adapters",
|
|
152
|
-
},
|
|
153
|
-
]
|
|
154
|
-
}
|
|
155
|
-
return list.map((item) => ({
|
|
156
|
-
title: item.name,
|
|
157
|
-
value: item.type,
|
|
158
|
-
description: item.description,
|
|
159
|
-
}))
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
const create = async (type: string) => {
|
|
163
|
-
if (creating()) return
|
|
164
|
-
setCreating(type)
|
|
165
|
-
|
|
166
|
-
const result = await sdk.client.experimental.workspace.create({ type, branch: null }).catch(() => {
|
|
167
|
-
toast.show({
|
|
168
|
-
message: "Creating workspace failed",
|
|
169
|
-
variant: "error",
|
|
170
|
-
})
|
|
171
|
-
return undefined
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
const workspace = result?.data
|
|
175
|
-
if (!workspace) {
|
|
176
|
-
setCreating(undefined)
|
|
177
|
-
toast.show({
|
|
178
|
-
message: `Failed to create workspace: ${errorMessage(result?.error ?? "no response")}`,
|
|
179
|
-
variant: "error",
|
|
180
|
-
})
|
|
181
|
-
return
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
await project.workspace.sync()
|
|
185
|
-
await props.onSelect(workspace.id)
|
|
186
|
-
setCreating(undefined)
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return (
|
|
190
|
-
<DialogSelect
|
|
191
|
-
title={creating() ? "Creating Workspace" : "New Workspace"}
|
|
192
|
-
skipFilter={true}
|
|
193
|
-
options={options()}
|
|
194
|
-
onSelect={(option) => {
|
|
195
|
-
if (option.value === "creating" || option.value === "loading") return
|
|
196
|
-
void create(option.value)
|
|
197
|
-
}}
|
|
198
|
-
/>
|
|
199
|
-
)
|
|
200
|
-
}
|
|
1
|
+
export * from "./dialog/dialog-workspace-create"
|
|
@@ -1,81 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { useKeyboard } from "@opentui/solid"
|
|
3
|
-
import { createStore } from "solid-js/store"
|
|
4
|
-
import { For } from "solid-js"
|
|
5
|
-
import { useTheme } from "../context/theme"
|
|
6
|
-
import { useDialog } from "../ui/dialog"
|
|
7
|
-
|
|
8
|
-
export function DialogWorkspaceUnavailable(props: { onRestore?: () => boolean | void | Promise<boolean | void> }) {
|
|
9
|
-
const dialog = useDialog()
|
|
10
|
-
const { theme } = useTheme()
|
|
11
|
-
const [store, setStore] = createStore({
|
|
12
|
-
active: "restore" as "cancel" | "restore",
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
const options = ["cancel", "restore"] as const
|
|
16
|
-
|
|
17
|
-
async function confirm() {
|
|
18
|
-
if (store.active === "cancel") {
|
|
19
|
-
dialog.clear()
|
|
20
|
-
return
|
|
21
|
-
}
|
|
22
|
-
const result = await props.onRestore?.()
|
|
23
|
-
if (result === false) return
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
useKeyboard((evt) => {
|
|
27
|
-
if (evt.name === "return") {
|
|
28
|
-
evt.preventDefault()
|
|
29
|
-
evt.stopPropagation()
|
|
30
|
-
void confirm()
|
|
31
|
-
return
|
|
32
|
-
}
|
|
33
|
-
if (evt.name === "left") {
|
|
34
|
-
evt.preventDefault()
|
|
35
|
-
evt.stopPropagation()
|
|
36
|
-
setStore("active", "cancel")
|
|
37
|
-
return
|
|
38
|
-
}
|
|
39
|
-
if (evt.name === "right") {
|
|
40
|
-
evt.preventDefault()
|
|
41
|
-
evt.stopPropagation()
|
|
42
|
-
setStore("active", "restore")
|
|
43
|
-
}
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
return (
|
|
47
|
-
<box paddingLeft={2} paddingRight={2} gap={1}>
|
|
48
|
-
<box flexDirection="row" justifyContent="space-between">
|
|
49
|
-
<text attributes={TextAttributes.BOLD} fg={theme.text}>
|
|
50
|
-
Workspace Unavailable
|
|
51
|
-
</text>
|
|
52
|
-
<text fg={theme.textMuted} onMouseUp={() => dialog.clear()}>
|
|
53
|
-
esc
|
|
54
|
-
</text>
|
|
55
|
-
</box>
|
|
56
|
-
<text fg={theme.textMuted} wrapMode="word">
|
|
57
|
-
This session is attached to a workspace that is no longer available.
|
|
58
|
-
</text>
|
|
59
|
-
<text fg={theme.textMuted} wrapMode="word">
|
|
60
|
-
Would you like to restore this session into a new workspace?
|
|
61
|
-
</text>
|
|
62
|
-
<box flexDirection="row" justifyContent="flex-end" paddingBottom={1} gap={1}>
|
|
63
|
-
<For each={options}>
|
|
64
|
-
{(item) => (
|
|
65
|
-
<box
|
|
66
|
-
paddingLeft={2}
|
|
67
|
-
paddingRight={2}
|
|
68
|
-
backgroundColor={item === store.active ? theme.primary : undefined}
|
|
69
|
-
onMouseUp={() => {
|
|
70
|
-
setStore("active", item)
|
|
71
|
-
void confirm()
|
|
72
|
-
}}
|
|
73
|
-
>
|
|
74
|
-
<text fg={item === store.active ? theme.selectedListItemText : theme.textMuted}>{item}</text>
|
|
75
|
-
</box>
|
|
76
|
-
)}
|
|
77
|
-
</For>
|
|
78
|
-
</box>
|
|
79
|
-
</box>
|
|
80
|
-
)
|
|
81
|
-
}
|
|
1
|
+
export * from "./dialog/dialog-workspace-unavailable"
|
|
@@ -1,169 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { BusEvent } from "@/bus/bus-event"
|
|
3
|
-
import { SessionID, MessageID } from "./schema"
|
|
4
|
-
import { Provider } from "@/provider/provider"
|
|
5
|
-
import { MessageV2 } from "./message-v2"
|
|
6
|
-
import { Schema, Effect } from "effect"
|
|
7
|
-
import { Config } from "@/config/config"
|
|
8
|
-
import { usable } from "./overflow"
|
|
9
|
-
|
|
10
|
-
export const PRUNE_MINIMUM = 20_000
|
|
11
|
-
export const PRUNE_PROTECT = 40_000
|
|
12
|
-
export const TOOL_OUTPUT_MAX_CHARS = 2_000
|
|
13
|
-
export const PRUNE_PROTECTED_TOOLS = ["skill"]
|
|
14
|
-
export const DEFAULT_TAIL_TURNS = 2
|
|
15
|
-
export const MIN_PRESERVE_RECENT_TOKENS = 2_000
|
|
16
|
-
export const MAX_PRESERVE_RECENT_TOKENS = 8_000
|
|
17
|
-
export const SUMMARY_TEMPLATE = `Output exactly the Markdown structure shown inside <template> and keep the section order unchanged. Do not include the <template> tags in your response.
|
|
18
|
-
<template>
|
|
19
|
-
## Goal
|
|
20
|
-
- [single-sentence task summary]
|
|
21
|
-
|
|
22
|
-
## Constraints & Preferences
|
|
23
|
-
- [user constraints, preferences, specs, or "(none)"]
|
|
24
|
-
|
|
25
|
-
## Progress
|
|
26
|
-
### Done
|
|
27
|
-
- [completed work or "(none)"]
|
|
28
|
-
|
|
29
|
-
### In Progress
|
|
30
|
-
- [current work or "(none)"]
|
|
31
|
-
|
|
32
|
-
### Blocked
|
|
33
|
-
- [blockers or "(none)"]
|
|
34
|
-
|
|
35
|
-
## Key Decisions
|
|
36
|
-
- [decision and why, or "(none)"]
|
|
37
|
-
|
|
38
|
-
## Next Steps
|
|
39
|
-
- [ordered next actions or "(none)"]
|
|
40
|
-
|
|
41
|
-
## Critical Context
|
|
42
|
-
- [important technical facts, errors, open questions, or "(none)"]
|
|
43
|
-
|
|
44
|
-
## Relevant Files
|
|
45
|
-
- [file or directory path: why it matters, or "(none)"]
|
|
46
|
-
</template>
|
|
47
|
-
|
|
48
|
-
Rules:
|
|
49
|
-
- Keep every section, even when empty.
|
|
50
|
-
- Use terse bullets, not prose paragraphs.
|
|
51
|
-
- Preserve exact file paths, commands, error strings, and identifiers when known.
|
|
52
|
-
- Do not mention the summary process or that context was compacted.`
|
|
53
|
-
export type Turn = {
|
|
54
|
-
start: number
|
|
55
|
-
end: number
|
|
56
|
-
id: MessageID
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export type Tail = {
|
|
60
|
-
start: number
|
|
61
|
-
id: MessageID
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export type CompletedCompaction = {
|
|
65
|
-
userIndex: number
|
|
66
|
-
assistantIndex: number
|
|
67
|
-
summary: string | undefined
|
|
68
|
-
}
|
|
69
|
-
export type PruneReason = "normal" | "post-compaction" | "payload-limit"
|
|
70
|
-
|
|
71
|
-
export const Event = {
|
|
72
|
-
Compacted: BusEvent.define(
|
|
73
|
-
"session.compacted",
|
|
74
|
-
Schema.Struct({
|
|
75
|
-
sessionID: SessionID,
|
|
76
|
-
}),
|
|
77
|
-
),
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export function summaryText(message: MessageV2.WithParts) {
|
|
81
|
-
const text = message.parts
|
|
82
|
-
.filter((part): part is MessageV2.TextPart => part.type === "text")
|
|
83
|
-
.map((part) => part.text.trim())
|
|
84
|
-
.filter(Boolean)
|
|
85
|
-
.join("\n\n")
|
|
86
|
-
.trim()
|
|
87
|
-
return text || undefined
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export function completedCompactions(messages: MessageV2.WithParts[]) {
|
|
91
|
-
const users = new Map<MessageID, number>()
|
|
92
|
-
for (let i = 0; i < messages.length; i++) {
|
|
93
|
-
const msg = messages[i]
|
|
94
|
-
if (msg.info.role !== "user") continue
|
|
95
|
-
if (!msg.parts.some((part) => part.type === "compaction")) continue
|
|
96
|
-
users.set(msg.info.id, i)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return messages.flatMap((msg, assistantIndex): CompletedCompaction[] => {
|
|
100
|
-
if (msg.info.role !== "assistant") return []
|
|
101
|
-
if (!msg.info.summary || !msg.info.finish || msg.info.error) return []
|
|
102
|
-
const userIndex = users.get(msg.info.parentID)
|
|
103
|
-
if (userIndex === undefined) return []
|
|
104
|
-
return [{ userIndex, assistantIndex, summary: summaryText(msg) }]
|
|
105
|
-
})
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export function buildPrompt(input: { previousSummary?: string; context: string[] }) {
|
|
109
|
-
const anchor = input.previousSummary
|
|
110
|
-
? [
|
|
111
|
-
"Update the anchored summary below using the conversation history above.",
|
|
112
|
-
"Preserve still-true details, remove stale details, and merge in the new facts.",
|
|
113
|
-
"<previous-summary>",
|
|
114
|
-
input.previousSummary,
|
|
115
|
-
"</previous-summary>",
|
|
116
|
-
].join("\n")
|
|
117
|
-
: "Create a new anchored summary from the conversation history above."
|
|
118
|
-
return [anchor, SUMMARY_TEMPLATE, ...input.context].join("\n\n")
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export function preserveRecentBudget(input: { cfg: Config.Info; model: Provider.Model }) {
|
|
122
|
-
return (
|
|
123
|
-
input.cfg.compaction?.preserve_recent_tokens ??
|
|
124
|
-
clamp(Math.floor(usable(input) * 0.25), MIN_PRESERVE_RECENT_TOKENS, MAX_PRESERVE_RECENT_TOKENS)
|
|
125
|
-
)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export function turns(messages: MessageV2.WithParts[]) {
|
|
129
|
-
const result: Turn[] = []
|
|
130
|
-
for (let i = 0; i < messages.length; i++) {
|
|
131
|
-
const msg = messages[i]
|
|
132
|
-
if (msg.info.role !== "user") continue
|
|
133
|
-
if (msg.parts.some((part) => part.type === "compaction")) continue
|
|
134
|
-
result.push({
|
|
135
|
-
start: i,
|
|
136
|
-
end: messages.length,
|
|
137
|
-
id: msg.info.id,
|
|
138
|
-
})
|
|
139
|
-
}
|
|
140
|
-
for (let i = 0; i < result.length - 1; i++) {
|
|
141
|
-
result[i].end = result[i + 1].start
|
|
142
|
-
}
|
|
143
|
-
return result
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
export function splitTurn(input: {
|
|
147
|
-
messages: MessageV2.WithParts[]
|
|
148
|
-
turn: Turn
|
|
149
|
-
model: Provider.Model
|
|
150
|
-
budget: number
|
|
151
|
-
estimate: (input: { messages: MessageV2.WithParts[]; model: Provider.Model }) => Effect.Effect<number>
|
|
152
|
-
}) {
|
|
153
|
-
return Effect.gen(function* () {
|
|
154
|
-
if (input.budget <= 0) return undefined
|
|
155
|
-
if (input.turn.end - input.turn.start <= 1) return undefined
|
|
156
|
-
for (let start = input.turn.start + 1; start < input.turn.end; start++) {
|
|
157
|
-
const size = yield* input.estimate({
|
|
158
|
-
messages: input.messages.slice(start, input.turn.end),
|
|
159
|
-
model: input.model,
|
|
160
|
-
})
|
|
161
|
-
if (size > input.budget) continue
|
|
162
|
-
return {
|
|
163
|
-
start,
|
|
164
|
-
id: input.messages[start]!.info.id,
|
|
165
|
-
} satisfies Tail
|
|
166
|
-
}
|
|
167
|
-
return undefined
|
|
168
|
-
})
|
|
169
|
-
}
|
|
1
|
+
export * from "./core/compaction/compaction-helpers"
|