saeeol 1.2.1 → 1.2.3

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.
Files changed (151) hide show
  1. package/bin/saeeol.cjs +187 -0
  2. package/npm/bin/saeeol +0 -0
  3. package/package.json +12 -12
  4. package/src/cli/cmd/tui/component/dialog/dialog-agent.tsx +32 -0
  5. package/src/cli/cmd/tui/component/dialog/dialog-command.tsx +190 -0
  6. package/src/cli/cmd/tui/component/dialog/dialog-console-org.tsx +103 -0
  7. package/src/cli/cmd/tui/component/dialog/dialog-go-upsell.tsx +159 -0
  8. package/src/cli/cmd/tui/component/dialog/dialog-mcp.tsx +86 -0
  9. package/src/cli/cmd/tui/component/dialog/dialog-model.tsx +238 -0
  10. package/src/cli/cmd/tui/component/dialog/dialog-provider.tsx +343 -0
  11. package/src/cli/cmd/tui/component/dialog/dialog-session-delete-failed.tsx +103 -0
  12. package/src/cli/cmd/tui/component/dialog/dialog-session-list.tsx +301 -0
  13. package/src/cli/cmd/tui/component/dialog/dialog-session-rename.tsx +35 -0
  14. package/src/cli/cmd/tui/component/dialog/dialog-skill.tsx +37 -0
  15. package/src/cli/cmd/tui/component/dialog/dialog-stash.tsx +87 -0
  16. package/src/cli/cmd/tui/component/dialog/dialog-status.tsx +190 -0
  17. package/src/cli/cmd/tui/component/dialog/dialog-tag.tsx +44 -0
  18. package/src/cli/cmd/tui/component/dialog/dialog-theme-list.tsx +50 -0
  19. package/src/cli/cmd/tui/component/dialog/dialog-variant.tsx +39 -0
  20. package/src/cli/cmd/tui/component/dialog/dialog-workspace-create.tsx +200 -0
  21. package/src/cli/cmd/tui/component/dialog/dialog-workspace-unavailable.tsx +81 -0
  22. package/src/cli/cmd/tui/component/dialog-agent.tsx +1 -32
  23. package/src/cli/cmd/tui/component/dialog-command.tsx +1 -190
  24. package/src/cli/cmd/tui/component/dialog-console-org.tsx +1 -103
  25. package/src/cli/cmd/tui/component/dialog-go-upsell.tsx +1 -159
  26. package/src/cli/cmd/tui/component/dialog-mcp.tsx +1 -86
  27. package/src/cli/cmd/tui/component/dialog-model.tsx +1 -238
  28. package/src/cli/cmd/tui/component/dialog-provider.tsx +1 -343
  29. package/src/cli/cmd/tui/component/dialog-session-delete-failed.tsx +1 -103
  30. package/src/cli/cmd/tui/component/dialog-session-list.tsx +1 -301
  31. package/src/cli/cmd/tui/component/dialog-session-rename.tsx +1 -35
  32. package/src/cli/cmd/tui/component/dialog-skill.tsx +1 -37
  33. package/src/cli/cmd/tui/component/dialog-stash.tsx +1 -87
  34. package/src/cli/cmd/tui/component/dialog-status.tsx +1 -190
  35. package/src/cli/cmd/tui/component/dialog-tag.tsx +1 -44
  36. package/src/cli/cmd/tui/component/dialog-theme-list.tsx +1 -50
  37. package/src/cli/cmd/tui/component/dialog-variant.tsx +1 -39
  38. package/src/cli/cmd/tui/component/dialog-workspace-create.tsx +1 -200
  39. package/src/cli/cmd/tui/component/dialog-workspace-unavailable.tsx +1 -81
  40. package/src/cli/cmd/tui/context/app/args.tsx +15 -0
  41. package/src/cli/cmd/tui/context/app/directory.ts +15 -0
  42. package/src/cli/cmd/tui/context/app/editor-zed.ts +281 -0
  43. package/src/cli/cmd/tui/context/app/editor.ts +425 -0
  44. package/src/cli/cmd/tui/context/app/helper.tsx +25 -0
  45. package/src/cli/cmd/tui/context/app/project.tsx +109 -0
  46. package/src/cli/cmd/tui/context/app/route.tsx +67 -0
  47. package/src/cli/cmd/tui/context/app/sdk.tsx +142 -0
  48. package/src/cli/cmd/tui/context/app/sync.tsx +713 -0
  49. package/src/cli/cmd/tui/context/app/theme.tsx +307 -0
  50. package/src/cli/cmd/tui/context/app/tui-config.tsx +9 -0
  51. package/src/cli/cmd/tui/context/args.tsx +1 -15
  52. package/src/cli/cmd/tui/context/directory.ts +1 -15
  53. package/src/cli/cmd/tui/context/editor-zed.ts +1 -281
  54. package/src/cli/cmd/tui/context/editor.ts +1 -425
  55. package/src/cli/cmd/tui/context/event.ts +1 -45
  56. package/src/cli/cmd/tui/context/exit.tsx +1 -67
  57. package/src/cli/cmd/tui/context/helper.tsx +1 -25
  58. package/src/cli/cmd/tui/context/keybind.tsx +1 -105
  59. package/src/cli/cmd/tui/context/kv.tsx +1 -76
  60. package/src/cli/cmd/tui/context/local.tsx +1 -478
  61. package/src/cli/cmd/tui/context/plugin-keybinds.ts +1 -41
  62. package/src/cli/cmd/tui/context/project.tsx +1 -109
  63. package/src/cli/cmd/tui/context/prompt.tsx +1 -18
  64. package/src/cli/cmd/tui/context/route.tsx +1 -67
  65. package/src/cli/cmd/tui/context/runtime/event.ts +45 -0
  66. package/src/cli/cmd/tui/context/runtime/exit.tsx +67 -0
  67. package/src/cli/cmd/tui/context/runtime/keybind.tsx +105 -0
  68. package/src/cli/cmd/tui/context/runtime/kv.tsx +76 -0
  69. package/src/cli/cmd/tui/context/runtime/local.tsx +478 -0
  70. package/src/cli/cmd/tui/context/runtime/plugin-keybinds.ts +41 -0
  71. package/src/cli/cmd/tui/context/sdk.tsx +1 -142
  72. package/src/cli/cmd/tui/context/session/prompt.tsx +18 -0
  73. package/src/cli/cmd/tui/context/sync.tsx +1 -713
  74. package/src/cli/cmd/tui/context/theme.tsx +1 -307
  75. package/src/cli/cmd/tui/context/tui-config.tsx +1 -9
  76. package/src/tool/apply_patch.ts +1 -334
  77. package/src/tool/bash.ts +1 -656
  78. package/src/tool/core/external-directory.ts +55 -0
  79. package/src/tool/core/invalid.ts +21 -0
  80. package/src/tool/core/recall.ts +164 -0
  81. package/src/tool/core/recall.txt +12 -0
  82. package/src/tool/core/schema.ts +16 -0
  83. package/src/tool/core/tool.ts +162 -0
  84. package/src/tool/core/truncate.ts +160 -0
  85. package/src/tool/core/truncation-dir.ts +4 -0
  86. package/src/tool/diagnostics.ts +1 -20
  87. package/src/tool/edit-replacers.ts +1 -288
  88. package/src/tool/edit-utils.ts +1 -86
  89. package/src/tool/edit.ts +1 -262
  90. package/src/tool/external-directory.ts +1 -55
  91. package/src/tool/file/apply_patch.ts +334 -0
  92. package/src/tool/file/apply_patch.txt +33 -0
  93. package/src/tool/file/bash.ts +656 -0
  94. package/src/tool/file/bash.txt +119 -0
  95. package/src/tool/file/edit-replacers.ts +288 -0
  96. package/src/tool/file/edit-utils.ts +86 -0
  97. package/src/tool/file/edit.ts +262 -0
  98. package/src/tool/file/edit.txt +10 -0
  99. package/src/tool/file/read.ts +389 -0
  100. package/src/tool/file/read.txt +14 -0
  101. package/src/tool/file/write.ts +114 -0
  102. package/src/tool/file/write.txt +8 -0
  103. package/src/tool/glob.ts +1 -115
  104. package/src/tool/grep.ts +1 -151
  105. package/src/tool/integration/diagnostics.ts +20 -0
  106. package/src/tool/integration/lsp.ts +113 -0
  107. package/src/tool/integration/lsp.txt +24 -0
  108. package/src/tool/integration/mcp-exa.ts +73 -0
  109. package/src/tool/integration/package.ts +168 -0
  110. package/src/tool/integration/registry.ts +375 -0
  111. package/src/tool/invalid.ts +1 -21
  112. package/src/tool/lsp.ts +1 -113
  113. package/src/tool/mcp-exa.ts +1 -73
  114. package/src/tool/package.ts +1 -168
  115. package/src/tool/plan.ts +1 -30
  116. package/src/tool/question.ts +1 -52
  117. package/src/tool/read.ts +1 -389
  118. package/src/tool/recall.ts +1 -164
  119. package/src/tool/registry.ts +1 -375
  120. package/src/tool/schema.ts +1 -16
  121. package/src/tool/search/glob.ts +115 -0
  122. package/src/tool/search/glob.txt +6 -0
  123. package/src/tool/search/grep.ts +151 -0
  124. package/src/tool/search/grep.txt +8 -0
  125. package/src/tool/search/warpgrep.ts +107 -0
  126. package/src/tool/search/warpgrep.txt +10 -0
  127. package/src/tool/search/webfetch.ts +202 -0
  128. package/src/tool/search/webfetch.txt +13 -0
  129. package/src/tool/search/websearch.ts +71 -0
  130. package/src/tool/search/websearch.txt +14 -0
  131. package/src/tool/skill.ts +1 -91
  132. package/src/tool/task.ts +1 -197
  133. package/src/tool/todo.ts +1 -62
  134. package/src/tool/tool.ts +1 -162
  135. package/src/tool/truncate.ts +1 -160
  136. package/src/tool/truncation-dir.ts +1 -4
  137. package/src/tool/warpgrep.ts +1 -107
  138. package/src/tool/webfetch.ts +1 -202
  139. package/src/tool/websearch.ts +1 -71
  140. package/src/tool/workflow/plan-enter.txt +14 -0
  141. package/src/tool/workflow/plan-exit.txt +13 -0
  142. package/src/tool/workflow/plan.ts +30 -0
  143. package/src/tool/workflow/question.ts +52 -0
  144. package/src/tool/workflow/question.txt +11 -0
  145. package/src/tool/workflow/skill.ts +91 -0
  146. package/src/tool/workflow/skill.txt +5 -0
  147. package/src/tool/workflow/task.ts +197 -0
  148. package/src/tool/workflow/task.txt +57 -0
  149. package/src/tool/workflow/todo.ts +62 -0
  150. package/src/tool/workflow/todowrite.txt +167 -0
  151. package/src/tool/write.ts +1 -114
@@ -1,44 +1 @@
1
- import { createMemo, createResource } from "solid-js"
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
- import { DialogSelect, type DialogSelectRef } from "../ui/dialog-select"
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
- import { createMemo } from "solid-js"
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
- import { createSaeeolClient } from "@saeeol/sdk/v2"
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
- import { TextAttributes } from "@opentui/core"
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"
@@ -0,0 +1,15 @@
1
+ import { createSimpleContext } from "./helper"
2
+
3
+ export interface Args {
4
+ model?: string
5
+ agent?: string
6
+ prompt?: string
7
+ continue?: boolean
8
+ sessionID?: string
9
+ fork?: boolean
10
+ }
11
+
12
+ export const { use: useArgs, provider: ArgsProvider } = createSimpleContext({
13
+ name: "Args",
14
+ init: (props: Args) => props,
15
+ })
@@ -0,0 +1,15 @@
1
+ import { createMemo } from "solid-js"
2
+ import { useProject } from "../app/project"
3
+ import { useSync } from "../app/sync"
4
+ import { Global } from "@saeeol/core/global"
5
+
6
+ export function useDirectory() {
7
+ const project = useProject()
8
+ const sync = useSync()
9
+ return createMemo(() => {
10
+ const directory = project.instance.path().directory || process.cwd()
11
+ const result = directory.replace(Global.Path.home, "~")
12
+ if (sync.data.vcs?.branch) return result + ":" + sync.data.vcs.branch
13
+ return result
14
+ })
15
+ }