tulingcode-plugin 0.2.0 → 0.3.1
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 +3 -3
- package/src/example-workspace.ts +34 -0
- package/src/example.ts +18 -0
- package/src/index.ts +428 -0
- package/src/shell.ts +136 -0
- package/src/tool.ts +41 -0
- package/src/tui.ts +526 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "tulingcode-plugin",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"publishConfig": {
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
"./tui": "./src/tui.ts"
|
|
18
18
|
},
|
|
19
19
|
"files": [
|
|
20
|
-
"
|
|
20
|
+
"src"
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"tulingcode-sdk": "0.
|
|
23
|
+
"tulingcode-sdk": "0.2.0",
|
|
24
24
|
"effect": "4.0.0-beta.48",
|
|
25
25
|
"zod": "4.1.8"
|
|
26
26
|
},
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Plugin } from "@tuling-ai/plugin"
|
|
2
|
+
import { mkdir, rm } from "node:fs/promises"
|
|
3
|
+
|
|
4
|
+
export const FolderWorkspacePlugin: Plugin = async ({ experimental_workspace }) => {
|
|
5
|
+
experimental_workspace.register("folder", {
|
|
6
|
+
name: "Folder",
|
|
7
|
+
description: "Create a blank folder",
|
|
8
|
+
configure(config) {
|
|
9
|
+
const rand = "" + Math.random()
|
|
10
|
+
|
|
11
|
+
return {
|
|
12
|
+
...config,
|
|
13
|
+
directory: `/tmp/folder/folder-${rand}`,
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
async create(config) {
|
|
17
|
+
if (!config.directory) return
|
|
18
|
+
await mkdir(config.directory, { recursive: true })
|
|
19
|
+
},
|
|
20
|
+
async remove(config) {
|
|
21
|
+
await rm(config.directory!, { recursive: true, force: true })
|
|
22
|
+
},
|
|
23
|
+
target(config) {
|
|
24
|
+
return {
|
|
25
|
+
type: "local",
|
|
26
|
+
directory: config.directory!,
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
return {}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default FolderWorkspacePlugin
|
package/src/example.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Plugin } from "./index.js"
|
|
2
|
+
import { tool } from "./tool.js"
|
|
3
|
+
|
|
4
|
+
export const ExamplePlugin: Plugin = async (_ctx) => {
|
|
5
|
+
return {
|
|
6
|
+
tool: {
|
|
7
|
+
mytool: tool({
|
|
8
|
+
description: "This is a custom tool",
|
|
9
|
+
args: {
|
|
10
|
+
foo: tool.schema.string().describe("foo"),
|
|
11
|
+
},
|
|
12
|
+
async execute(args) {
|
|
13
|
+
return `Hello ${args.foo}!`
|
|
14
|
+
},
|
|
15
|
+
}),
|
|
16
|
+
},
|
|
17
|
+
}
|
|
18
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Event,
|
|
3
|
+
createTulingcodeClient,
|
|
4
|
+
Project,
|
|
5
|
+
Model,
|
|
6
|
+
Provider,
|
|
7
|
+
Permission,
|
|
8
|
+
UserMessage,
|
|
9
|
+
Message,
|
|
10
|
+
Part,
|
|
11
|
+
Auth,
|
|
12
|
+
Config as SDKConfig,
|
|
13
|
+
} from "@tuling-ai/sdk"
|
|
14
|
+
import type { Provider as ProviderV2, Model as ModelV2 } from "@tuling-ai/sdk/v2"
|
|
15
|
+
|
|
16
|
+
import type { BunShell } from "./shell.js"
|
|
17
|
+
import { type ToolDefinition } from "./tool.js"
|
|
18
|
+
|
|
19
|
+
export * from "./tool.js"
|
|
20
|
+
|
|
21
|
+
export type ProviderContext = {
|
|
22
|
+
source: "env" | "config" | "custom" | "api"
|
|
23
|
+
info: Provider
|
|
24
|
+
options: Record<string, any>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type WorkspaceInfo = {
|
|
28
|
+
id: string
|
|
29
|
+
type: string
|
|
30
|
+
name: string
|
|
31
|
+
branch: string | null
|
|
32
|
+
directory: string | null
|
|
33
|
+
extra: unknown | null
|
|
34
|
+
projectID: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type WorkspaceTarget =
|
|
38
|
+
| {
|
|
39
|
+
type: "local"
|
|
40
|
+
directory: string
|
|
41
|
+
}
|
|
42
|
+
| {
|
|
43
|
+
type: "remote"
|
|
44
|
+
url: string | URL
|
|
45
|
+
headers?: HeadersInit
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type WorkspaceAdaptor = {
|
|
49
|
+
name: string
|
|
50
|
+
description: string
|
|
51
|
+
configure(config: WorkspaceInfo): WorkspaceInfo | Promise<WorkspaceInfo>
|
|
52
|
+
create(config: WorkspaceInfo, env: Record<string, string | undefined>, from?: WorkspaceInfo): Promise<void>
|
|
53
|
+
remove(config: WorkspaceInfo): Promise<void>
|
|
54
|
+
target(config: WorkspaceInfo): WorkspaceTarget | Promise<WorkspaceTarget>
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export type PluginInput = {
|
|
58
|
+
client: ReturnType<typeof createTulingcodeClient>
|
|
59
|
+
project: Project
|
|
60
|
+
directory: string
|
|
61
|
+
worktree: string
|
|
62
|
+
experimental_workspace: {
|
|
63
|
+
register(type: string, adaptor: WorkspaceAdaptor): void
|
|
64
|
+
}
|
|
65
|
+
serverUrl: URL
|
|
66
|
+
$: BunShell
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export type PluginOptions = Record<string, unknown>
|
|
70
|
+
|
|
71
|
+
export type Config = Omit<SDKConfig, "plugin"> & {
|
|
72
|
+
plugin?: Array<string | [string, PluginOptions]>
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export type Plugin = (input: PluginInput, options?: PluginOptions) => Promise<Hooks>
|
|
76
|
+
|
|
77
|
+
export type PluginModule = {
|
|
78
|
+
id?: string
|
|
79
|
+
server: Plugin
|
|
80
|
+
tui?: never
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
type Rule = {
|
|
84
|
+
key: string
|
|
85
|
+
op: "eq" | "neq"
|
|
86
|
+
value: string
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export type AuthHook = {
|
|
90
|
+
provider: string
|
|
91
|
+
loader?: (auth: () => Promise<Auth>, provider: Provider) => Promise<Record<string, any>>
|
|
92
|
+
methods: (
|
|
93
|
+
| {
|
|
94
|
+
type: "oauth"
|
|
95
|
+
label: string
|
|
96
|
+
prompts?: Array<
|
|
97
|
+
| {
|
|
98
|
+
type: "text"
|
|
99
|
+
key: string
|
|
100
|
+
message: string
|
|
101
|
+
placeholder?: string
|
|
102
|
+
validate?: (value: string) => string | undefined
|
|
103
|
+
/** @deprecated Use `when` instead */
|
|
104
|
+
condition?: (inputs: Record<string, string>) => boolean
|
|
105
|
+
when?: Rule
|
|
106
|
+
}
|
|
107
|
+
| {
|
|
108
|
+
type: "select"
|
|
109
|
+
key: string
|
|
110
|
+
message: string
|
|
111
|
+
options: Array<{
|
|
112
|
+
label: string
|
|
113
|
+
value: string
|
|
114
|
+
hint?: string
|
|
115
|
+
}>
|
|
116
|
+
/** @deprecated Use `when` instead */
|
|
117
|
+
condition?: (inputs: Record<string, string>) => boolean
|
|
118
|
+
when?: Rule
|
|
119
|
+
}
|
|
120
|
+
>
|
|
121
|
+
authorize(inputs?: Record<string, string>): Promise<AuthOAuthResult>
|
|
122
|
+
}
|
|
123
|
+
| {
|
|
124
|
+
type: "api"
|
|
125
|
+
label: string
|
|
126
|
+
prompts?: Array<
|
|
127
|
+
| {
|
|
128
|
+
type: "text"
|
|
129
|
+
key: string
|
|
130
|
+
message: string
|
|
131
|
+
placeholder?: string
|
|
132
|
+
validate?: (value: string) => string | undefined
|
|
133
|
+
/** @deprecated Use `when` instead */
|
|
134
|
+
condition?: (inputs: Record<string, string>) => boolean
|
|
135
|
+
when?: Rule
|
|
136
|
+
}
|
|
137
|
+
| {
|
|
138
|
+
type: "select"
|
|
139
|
+
key: string
|
|
140
|
+
message: string
|
|
141
|
+
options: Array<{
|
|
142
|
+
label: string
|
|
143
|
+
value: string
|
|
144
|
+
hint?: string
|
|
145
|
+
}>
|
|
146
|
+
/** @deprecated Use `when` instead */
|
|
147
|
+
condition?: (inputs: Record<string, string>) => boolean
|
|
148
|
+
when?: Rule
|
|
149
|
+
}
|
|
150
|
+
>
|
|
151
|
+
authorize?(inputs?: Record<string, string>): Promise<
|
|
152
|
+
| {
|
|
153
|
+
type: "success"
|
|
154
|
+
key: string
|
|
155
|
+
provider?: string
|
|
156
|
+
}
|
|
157
|
+
| {
|
|
158
|
+
type: "failed"
|
|
159
|
+
}
|
|
160
|
+
>
|
|
161
|
+
}
|
|
162
|
+
)[]
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export type AuthOAuthResult = { url: string; instructions: string } & (
|
|
166
|
+
| {
|
|
167
|
+
method: "auto"
|
|
168
|
+
callback(code?: string): Promise<
|
|
169
|
+
| ({
|
|
170
|
+
type: "success"
|
|
171
|
+
provider?: string
|
|
172
|
+
metadata?: Record<string, string>
|
|
173
|
+
} & (
|
|
174
|
+
| {
|
|
175
|
+
refresh: string
|
|
176
|
+
access: string
|
|
177
|
+
expires: number
|
|
178
|
+
accountId?: string
|
|
179
|
+
enterpriseUrl?: string
|
|
180
|
+
}
|
|
181
|
+
| { key: string }
|
|
182
|
+
))
|
|
183
|
+
| {
|
|
184
|
+
type: "failed"
|
|
185
|
+
}
|
|
186
|
+
>
|
|
187
|
+
}
|
|
188
|
+
| {
|
|
189
|
+
method: "code"
|
|
190
|
+
callback(code: string): Promise<
|
|
191
|
+
| ({
|
|
192
|
+
type: "success"
|
|
193
|
+
provider?: string
|
|
194
|
+
metadata?: Record<string, string>
|
|
195
|
+
} & (
|
|
196
|
+
| {
|
|
197
|
+
refresh: string
|
|
198
|
+
access: string
|
|
199
|
+
expires: number
|
|
200
|
+
accountId?: string
|
|
201
|
+
enterpriseUrl?: string
|
|
202
|
+
}
|
|
203
|
+
| { key: string }
|
|
204
|
+
))
|
|
205
|
+
| {
|
|
206
|
+
type: "failed"
|
|
207
|
+
}
|
|
208
|
+
>
|
|
209
|
+
}
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
export type ProviderHookContext = {
|
|
213
|
+
auth?: Auth
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export type ProviderHook = {
|
|
217
|
+
id: string
|
|
218
|
+
models?: (provider: ProviderV2, ctx: ProviderHookContext) => Promise<Record<string, ModelV2>>
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** @deprecated Use AuthOAuthResult instead. */
|
|
222
|
+
export type AuthOuathResult = AuthOAuthResult
|
|
223
|
+
|
|
224
|
+
// ----- Actor lifecycle hook types -----
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Agent types excluded from actor.preStop / actor.postStop by default.
|
|
228
|
+
* Includes the agents registered in src/agent/agent.ts plus runtime-only
|
|
229
|
+
* pseudo-agents ("main" = root actor, "compaction" = auto-compaction subsystem)
|
|
230
|
+
* that are never spawned via the agent registry.
|
|
231
|
+
*/
|
|
232
|
+
export const BUILT_IN_AGENTS = [
|
|
233
|
+
"main", "general", "build", "explore", "summary",
|
|
234
|
+
"title", "checkpoint-writer", "dream", "distill", "compaction",
|
|
235
|
+
] as const
|
|
236
|
+
|
|
237
|
+
export type BuiltInAgent = (typeof BUILT_IN_AGENTS)[number]
|
|
238
|
+
export type ActorMode = "subagent" | "peer"
|
|
239
|
+
export type ActorLifecycle = "ephemeral" | "persistent"
|
|
240
|
+
export type ActorOutcome = "success" | "failure" | "cancelled"
|
|
241
|
+
|
|
242
|
+
export type ActorMatcher = {
|
|
243
|
+
mode?: ActorMode
|
|
244
|
+
agentType?:
|
|
245
|
+
| string
|
|
246
|
+
| string[]
|
|
247
|
+
| { include: string[]; exclude?: string[] }
|
|
248
|
+
| { excludeOnly: string[] } // matches every agent (incl. built-ins) except those listed
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export type ActorStopBaseInput = {
|
|
252
|
+
sessionID: string
|
|
253
|
+
/** Parent session id when the actor runs in a child session (e.g. checkpoint-writer
|
|
254
|
+
* runs under a child session keyed on parent_id). Undefined when sessionID === parent.
|
|
255
|
+
* Plugins that re-derive paths from sessionID should read `parentSessionID ?? sessionID`. */
|
|
256
|
+
parentSessionID?: string
|
|
257
|
+
actorID: string
|
|
258
|
+
parentActorID?: string
|
|
259
|
+
agentType: string
|
|
260
|
+
mode: ActorMode
|
|
261
|
+
lifecycle: ActorLifecycle
|
|
262
|
+
task: string
|
|
263
|
+
description?: string
|
|
264
|
+
finalText?: string
|
|
265
|
+
task_id?: string // Spec ②: if set, postStop hooks can validate tasks/<task_id>/progress.md
|
|
266
|
+
iteration: number
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export type ActorPreStopInput = ActorStopBaseInput
|
|
270
|
+
|
|
271
|
+
export type ActorPostStopInput = ActorStopBaseInput & {
|
|
272
|
+
outcome: ActorOutcome
|
|
273
|
+
error?: string // outcome === "failure" 时存在
|
|
274
|
+
// false → the spawned agent cannot use the Write tool (read-only, e.g. explore).
|
|
275
|
+
// Absent/undefined → unknown; hooks must NOT suppress on absence (fail-open).
|
|
276
|
+
canWrite?: boolean
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export type ActorStopOutput = {
|
|
280
|
+
continue?: boolean
|
|
281
|
+
reason?: string
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export type ActorPreStopHook = (
|
|
285
|
+
input: ActorPreStopInput,
|
|
286
|
+
output: ActorStopOutput,
|
|
287
|
+
) => Promise<void>
|
|
288
|
+
|
|
289
|
+
export type ActorPostStopHook = (
|
|
290
|
+
input: ActorPostStopInput,
|
|
291
|
+
output: ActorStopOutput,
|
|
292
|
+
) => Promise<void>
|
|
293
|
+
|
|
294
|
+
export type ActorPreStopRegistration =
|
|
295
|
+
| ActorPreStopHook
|
|
296
|
+
| { matcher?: ActorMatcher; run: ActorPreStopHook }
|
|
297
|
+
|
|
298
|
+
export type ActorPostStopRegistration =
|
|
299
|
+
| ActorPostStopHook
|
|
300
|
+
| { matcher?: ActorMatcher; run: ActorPostStopHook }
|
|
301
|
+
|
|
302
|
+
export interface Hooks {
|
|
303
|
+
event?: (input: { event: Event }) => Promise<void>
|
|
304
|
+
config?: (input: Config) => Promise<void>
|
|
305
|
+
tool?: {
|
|
306
|
+
[key: string]: ToolDefinition
|
|
307
|
+
}
|
|
308
|
+
auth?: AuthHook
|
|
309
|
+
provider?: ProviderHook
|
|
310
|
+
/**
|
|
311
|
+
* Called when a new message is received
|
|
312
|
+
*/
|
|
313
|
+
"chat.message"?: (
|
|
314
|
+
input: {
|
|
315
|
+
sessionID: string
|
|
316
|
+
agent?: string
|
|
317
|
+
model?: { providerID: string; modelID: string }
|
|
318
|
+
messageID?: string
|
|
319
|
+
variant?: string
|
|
320
|
+
},
|
|
321
|
+
output: { message: UserMessage; parts: Part[] },
|
|
322
|
+
) => Promise<void>
|
|
323
|
+
/**
|
|
324
|
+
* Modify parameters sent to LLM
|
|
325
|
+
*/
|
|
326
|
+
"chat.params"?: (
|
|
327
|
+
input: { sessionID: string; agent: string; model: Model; provider: ProviderContext; message: UserMessage },
|
|
328
|
+
output: {
|
|
329
|
+
temperature: number
|
|
330
|
+
topP: number
|
|
331
|
+
topK: number
|
|
332
|
+
maxOutputTokens: number | undefined
|
|
333
|
+
options: Record<string, any>
|
|
334
|
+
},
|
|
335
|
+
) => Promise<void>
|
|
336
|
+
"chat.headers"?: (
|
|
337
|
+
input: { sessionID: string; agent: string; model: Model; provider: ProviderContext; message: UserMessage },
|
|
338
|
+
output: { headers: Record<string, string> },
|
|
339
|
+
) => Promise<void>
|
|
340
|
+
"permission.ask"?: (input: Permission, output: { status: "ask" | "deny" | "allow" }) => Promise<void>
|
|
341
|
+
"command.execute.before"?: (
|
|
342
|
+
input: { command: string; sessionID: string; arguments: string },
|
|
343
|
+
output: { parts: Part[] },
|
|
344
|
+
) => Promise<void>
|
|
345
|
+
"tool.execute.before"?: (
|
|
346
|
+
input: { tool: string; sessionID: string; callID: string },
|
|
347
|
+
output: { args: any },
|
|
348
|
+
) => Promise<void>
|
|
349
|
+
"shell.env"?: (
|
|
350
|
+
input: { cwd: string; sessionID?: string; callID?: string },
|
|
351
|
+
output: { env: Record<string, string> },
|
|
352
|
+
) => Promise<void>
|
|
353
|
+
"tool.execute.after"?: (
|
|
354
|
+
input: { tool: string; sessionID: string; callID: string; args: any },
|
|
355
|
+
output: {
|
|
356
|
+
title: string
|
|
357
|
+
output: string
|
|
358
|
+
metadata: any
|
|
359
|
+
},
|
|
360
|
+
) => Promise<void>
|
|
361
|
+
"experimental.chat.messages.transform"?: (
|
|
362
|
+
input: {},
|
|
363
|
+
output: {
|
|
364
|
+
messages: {
|
|
365
|
+
info: Message
|
|
366
|
+
parts: Part[]
|
|
367
|
+
}[]
|
|
368
|
+
},
|
|
369
|
+
) => Promise<void>
|
|
370
|
+
"experimental.chat.system.transform"?: (
|
|
371
|
+
input: { sessionID?: string; model: Model },
|
|
372
|
+
output: {
|
|
373
|
+
system: string[]
|
|
374
|
+
},
|
|
375
|
+
) => Promise<void>
|
|
376
|
+
/**
|
|
377
|
+
* Called before session compaction starts. Allows plugins to customize
|
|
378
|
+
* the compaction prompt.
|
|
379
|
+
*
|
|
380
|
+
* - `context`: Additional context strings appended to the default prompt
|
|
381
|
+
* - `prompt`: If set, replaces the default compaction prompt entirely
|
|
382
|
+
*/
|
|
383
|
+
"experimental.session.compacting"?: (
|
|
384
|
+
input: { sessionID: string },
|
|
385
|
+
output: { context: string[]; prompt?: string },
|
|
386
|
+
) => Promise<void>
|
|
387
|
+
/**
|
|
388
|
+
* Called after compaction succeeds and before a synthetic user
|
|
389
|
+
* auto-continue message is added.
|
|
390
|
+
*
|
|
391
|
+
* - `enabled`: Defaults to `true`. Set to `false` to skip the synthetic
|
|
392
|
+
* user "continue" turn.
|
|
393
|
+
*/
|
|
394
|
+
"experimental.compaction.autocontinue"?: (
|
|
395
|
+
input: {
|
|
396
|
+
sessionID: string
|
|
397
|
+
agent: string
|
|
398
|
+
model: Model
|
|
399
|
+
provider: ProviderContext
|
|
400
|
+
message: UserMessage
|
|
401
|
+
overflow: boolean
|
|
402
|
+
},
|
|
403
|
+
output: { enabled: boolean },
|
|
404
|
+
) => Promise<void>
|
|
405
|
+
"experimental.text.complete"?: (
|
|
406
|
+
input: { sessionID: string; messageID: string; partID: string },
|
|
407
|
+
output: { text: string },
|
|
408
|
+
) => Promise<void>
|
|
409
|
+
/**
|
|
410
|
+
* Modify tool definitions (description and parameters) sent to LLM
|
|
411
|
+
*/
|
|
412
|
+
"tool.definition"?: (input: { toolID: string }, output: { description: string; parameters: any }) => Promise<void>
|
|
413
|
+
/**
|
|
414
|
+
* Fires when an actor (subagent or peer) is about to deliver finalText to its caller.
|
|
415
|
+
* Set `output.continue = true` with `output.reason = "..."` to inject the reason as a
|
|
416
|
+
* synthetic user message and have the actor run another turn before delivery.
|
|
417
|
+
* Default matcher excludes BUILT_IN_AGENTS.
|
|
418
|
+
*/
|
|
419
|
+
"actor.preStop"?: ActorPreStopRegistration
|
|
420
|
+
/**
|
|
421
|
+
* Fires AFTER an actor has delivered finalText to its caller. The actor stays alive
|
|
422
|
+
* until the postStop chain ends. Like preStop, can return continue=true with reason
|
|
423
|
+
* to make the actor run another turn — but the new finalText does NOT propagate to
|
|
424
|
+
* the caller (the caller already got finalText_locked at delivery time).
|
|
425
|
+
* Default matcher excludes BUILT_IN_AGENTS.
|
|
426
|
+
*/
|
|
427
|
+
"actor.postStop"?: ActorPostStopRegistration
|
|
428
|
+
}
|
package/src/shell.ts
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
export type ShellFunction = (input: Uint8Array) => Uint8Array
|
|
2
|
+
|
|
3
|
+
export type ShellExpression =
|
|
4
|
+
| { toString(): string }
|
|
5
|
+
| Array<ShellExpression>
|
|
6
|
+
| string
|
|
7
|
+
| { raw: string }
|
|
8
|
+
| ReadableStream
|
|
9
|
+
|
|
10
|
+
export interface BunShell {
|
|
11
|
+
(strings: TemplateStringsArray, ...expressions: ShellExpression[]): BunShellPromise
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Perform bash-like brace expansion on the given pattern.
|
|
15
|
+
* @param pattern - Brace pattern to expand
|
|
16
|
+
*/
|
|
17
|
+
braces(pattern: string): string[]
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Escape strings for input into shell commands.
|
|
21
|
+
*/
|
|
22
|
+
escape(input: string): string
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Change the default environment variables for shells created by this instance.
|
|
26
|
+
*/
|
|
27
|
+
env(newEnv?: Record<string, string | undefined>): BunShell
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Default working directory to use for shells created by this instance.
|
|
31
|
+
*/
|
|
32
|
+
cwd(newCwd?: string): BunShell
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Configure the shell to not throw an exception on non-zero exit codes.
|
|
36
|
+
*/
|
|
37
|
+
nothrow(): BunShell
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Configure whether or not the shell should throw an exception on non-zero exit codes.
|
|
41
|
+
*/
|
|
42
|
+
throws(shouldThrow: boolean): BunShell
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface BunShellPromise extends Promise<BunShellOutput> {
|
|
46
|
+
readonly stdin: WritableStream
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Change the current working directory of the shell.
|
|
50
|
+
*/
|
|
51
|
+
cwd(newCwd: string): this
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Set environment variables for the shell.
|
|
55
|
+
*/
|
|
56
|
+
env(newEnv: Record<string, string> | undefined): this
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* By default, the shell will write to the current process's stdout and stderr, as well as buffering that output.
|
|
60
|
+
* This configures the shell to only buffer the output.
|
|
61
|
+
*/
|
|
62
|
+
quiet(): this
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Read from stdout as a string, line by line
|
|
66
|
+
* Automatically calls quiet() to disable echoing to stdout.
|
|
67
|
+
*/
|
|
68
|
+
lines(): AsyncIterable<string>
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Read from stdout as a string.
|
|
72
|
+
* Automatically calls quiet() to disable echoing to stdout.
|
|
73
|
+
*/
|
|
74
|
+
text(encoding?: BufferEncoding): Promise<string>
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Read from stdout as a JSON object
|
|
78
|
+
* Automatically calls quiet()
|
|
79
|
+
*/
|
|
80
|
+
json(): Promise<any>
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Read from stdout as an ArrayBuffer
|
|
84
|
+
* Automatically calls quiet()
|
|
85
|
+
*/
|
|
86
|
+
arrayBuffer(): Promise<ArrayBuffer>
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Read from stdout as a Blob
|
|
90
|
+
* Automatically calls quiet()
|
|
91
|
+
*/
|
|
92
|
+
blob(): Promise<Blob>
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Configure the shell to not throw an exception on non-zero exit codes.
|
|
96
|
+
*/
|
|
97
|
+
nothrow(): this
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Configure whether or not the shell should throw an exception on non-zero exit codes.
|
|
101
|
+
*/
|
|
102
|
+
throws(shouldThrow: boolean): this
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface BunShellOutput {
|
|
106
|
+
readonly stdout: Buffer
|
|
107
|
+
readonly stderr: Buffer
|
|
108
|
+
readonly exitCode: number
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Read from stdout as a string
|
|
112
|
+
*/
|
|
113
|
+
text(encoding?: BufferEncoding): string
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Read from stdout as a JSON object
|
|
117
|
+
*/
|
|
118
|
+
json(): any
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Read from stdout as an ArrayBuffer
|
|
122
|
+
*/
|
|
123
|
+
arrayBuffer(): ArrayBuffer
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Read from stdout as an Uint8Array
|
|
127
|
+
*/
|
|
128
|
+
bytes(): Uint8Array
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Read from stdout as a Blob
|
|
132
|
+
*/
|
|
133
|
+
blob(): Blob
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export type BunShellError = Error & BunShellOutput
|
package/src/tool.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { z } from "zod"
|
|
2
|
+
import { Effect } from "effect"
|
|
3
|
+
|
|
4
|
+
export type ToolContext = {
|
|
5
|
+
sessionID: string
|
|
6
|
+
messageID: string
|
|
7
|
+
agent: string
|
|
8
|
+
/**
|
|
9
|
+
* Current project directory for this session.
|
|
10
|
+
* Prefer this over process.cwd() when resolving relative paths.
|
|
11
|
+
*/
|
|
12
|
+
directory: string
|
|
13
|
+
/**
|
|
14
|
+
* Project worktree root for this session.
|
|
15
|
+
* Useful for generating stable relative paths (e.g. path.relative(worktree, absPath)).
|
|
16
|
+
*/
|
|
17
|
+
worktree: string
|
|
18
|
+
abort: AbortSignal
|
|
19
|
+
metadata(input: { title?: string; metadata?: { [key: string]: any } }): void
|
|
20
|
+
ask(input: AskInput): Effect.Effect<void>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type AskInput = {
|
|
24
|
+
permission: string
|
|
25
|
+
patterns: string[]
|
|
26
|
+
always: string[]
|
|
27
|
+
metadata: { [key: string]: any }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type ToolResult = string | { output: string; metadata?: { [key: string]: any } }
|
|
31
|
+
|
|
32
|
+
export function tool<Args extends z.ZodRawShape>(input: {
|
|
33
|
+
description: string
|
|
34
|
+
args: Args
|
|
35
|
+
execute(args: z.infer<z.ZodObject<Args>>, context: ToolContext): Promise<ToolResult>
|
|
36
|
+
}) {
|
|
37
|
+
return input
|
|
38
|
+
}
|
|
39
|
+
tool.schema = z
|
|
40
|
+
|
|
41
|
+
export type ToolDefinition = ReturnType<typeof tool>
|
package/src/tui.ts
ADDED
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AgentPart,
|
|
3
|
+
TulingcodeClient,
|
|
4
|
+
Event,
|
|
5
|
+
FilePart,
|
|
6
|
+
LspStatus,
|
|
7
|
+
McpStatus,
|
|
8
|
+
Todo,
|
|
9
|
+
SessionTaskResponse,
|
|
10
|
+
Message,
|
|
11
|
+
Part,
|
|
12
|
+
Provider,
|
|
13
|
+
PermissionRequest,
|
|
14
|
+
QuestionRequest,
|
|
15
|
+
SessionStatus,
|
|
16
|
+
TextPart,
|
|
17
|
+
Config as SdkConfig,
|
|
18
|
+
} from "@tuling-ai/sdk/v2"
|
|
19
|
+
import type { CliRenderer, ParsedKey, RGBA, SlotMode } from "@opentui/core"
|
|
20
|
+
import type { JSX, SolidPlugin } from "@opentui/solid"
|
|
21
|
+
import type { Config as PluginConfig, PluginOptions } from "./index.js"
|
|
22
|
+
|
|
23
|
+
export type { CliRenderer, SlotMode } from "@opentui/core"
|
|
24
|
+
|
|
25
|
+
export type TuiRouteCurrent =
|
|
26
|
+
| {
|
|
27
|
+
name: "home"
|
|
28
|
+
}
|
|
29
|
+
| {
|
|
30
|
+
name: "session"
|
|
31
|
+
params: {
|
|
32
|
+
sessionID: string
|
|
33
|
+
prompt?: unknown
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
| {
|
|
37
|
+
name: string
|
|
38
|
+
params?: Record<string, unknown>
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export type TuiRouteDefinition = {
|
|
42
|
+
name: string
|
|
43
|
+
render: (input: { params?: Record<string, unknown> }) => JSX.Element
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type TuiCommand = {
|
|
47
|
+
title: string
|
|
48
|
+
value: string
|
|
49
|
+
description?: string
|
|
50
|
+
category?: string
|
|
51
|
+
keybind?: string
|
|
52
|
+
suggested?: boolean
|
|
53
|
+
hidden?: boolean
|
|
54
|
+
enabled?: boolean
|
|
55
|
+
slash?: {
|
|
56
|
+
name: string
|
|
57
|
+
aliases?: string[]
|
|
58
|
+
}
|
|
59
|
+
onSelect?: () => void
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type TuiKeybind = {
|
|
63
|
+
name: string
|
|
64
|
+
ctrl: boolean
|
|
65
|
+
meta: boolean
|
|
66
|
+
shift: boolean
|
|
67
|
+
super?: boolean
|
|
68
|
+
leader: boolean
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export type TuiKeybindMap = Record<string, string>
|
|
72
|
+
|
|
73
|
+
export type TuiKeybindSet = {
|
|
74
|
+
readonly all: TuiKeybindMap
|
|
75
|
+
get: (name: string) => string
|
|
76
|
+
match: (name: string, evt: ParsedKey) => boolean
|
|
77
|
+
print: (name: string) => string
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export type TuiDialogProps = {
|
|
81
|
+
size?: "medium" | "large" | "xlarge"
|
|
82
|
+
onClose: () => void
|
|
83
|
+
children?: JSX.Element
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export type TuiDialogStack = {
|
|
87
|
+
replace: (render: () => JSX.Element, onClose?: () => void) => void
|
|
88
|
+
clear: () => void
|
|
89
|
+
setSize: (size: "medium" | "large" | "xlarge") => void
|
|
90
|
+
readonly size: "medium" | "large" | "xlarge"
|
|
91
|
+
readonly depth: number
|
|
92
|
+
readonly open: boolean
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export type TuiDialogAlertProps = {
|
|
96
|
+
title: string
|
|
97
|
+
message: string
|
|
98
|
+
onConfirm?: () => void
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export type TuiDialogConfirmProps = {
|
|
102
|
+
title: string
|
|
103
|
+
message: string
|
|
104
|
+
onConfirm?: () => void
|
|
105
|
+
onCancel?: () => void
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export type TuiDialogPromptProps = {
|
|
109
|
+
title: string
|
|
110
|
+
description?: () => JSX.Element
|
|
111
|
+
placeholder?: string
|
|
112
|
+
value?: string
|
|
113
|
+
busy?: boolean
|
|
114
|
+
busyText?: string
|
|
115
|
+
onConfirm?: (value: string) => void
|
|
116
|
+
onCancel?: () => void
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export type TuiDialogSelectOption<Value = unknown> = {
|
|
120
|
+
title: string
|
|
121
|
+
value: Value
|
|
122
|
+
description?: string
|
|
123
|
+
footer?: JSX.Element | string
|
|
124
|
+
category?: string
|
|
125
|
+
disabled?: boolean
|
|
126
|
+
onSelect?: () => void
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export type TuiDialogSelectProps<Value = unknown> = {
|
|
130
|
+
title: string
|
|
131
|
+
placeholder?: string
|
|
132
|
+
options: TuiDialogSelectOption<Value>[]
|
|
133
|
+
flat?: boolean
|
|
134
|
+
onMove?: (option: TuiDialogSelectOption<Value>) => void
|
|
135
|
+
onFilter?: (query: string) => void
|
|
136
|
+
onSelect?: (option: TuiDialogSelectOption<Value>) => void
|
|
137
|
+
skipFilter?: boolean
|
|
138
|
+
current?: Value
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export type TuiPromptInfo = {
|
|
142
|
+
input: string
|
|
143
|
+
mode?: "normal" | "shell"
|
|
144
|
+
parts: (
|
|
145
|
+
| Omit<FilePart, "id" | "messageID" | "sessionID">
|
|
146
|
+
| Omit<AgentPart, "id" | "messageID" | "sessionID">
|
|
147
|
+
| (Omit<TextPart, "id" | "messageID" | "sessionID"> & {
|
|
148
|
+
source?: {
|
|
149
|
+
text: {
|
|
150
|
+
start: number
|
|
151
|
+
end: number
|
|
152
|
+
value: string
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
})
|
|
156
|
+
)[]
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export type TuiPromptRef = {
|
|
160
|
+
focused: boolean
|
|
161
|
+
current: TuiPromptInfo
|
|
162
|
+
set(prompt: TuiPromptInfo): void
|
|
163
|
+
reset(): void
|
|
164
|
+
blur(): void
|
|
165
|
+
focus(): void
|
|
166
|
+
submit(): void
|
|
167
|
+
paste(): void
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export type TuiPromptProps = {
|
|
171
|
+
sessionID?: string
|
|
172
|
+
workspaceID?: string
|
|
173
|
+
visible?: boolean
|
|
174
|
+
disabled?: boolean
|
|
175
|
+
onSubmit?: () => void
|
|
176
|
+
ref?: (ref: TuiPromptRef | undefined) => void
|
|
177
|
+
hint?: JSX.Element
|
|
178
|
+
right?: JSX.Element
|
|
179
|
+
showPlaceholder?: boolean
|
|
180
|
+
placeholders?: {
|
|
181
|
+
normal?: string[]
|
|
182
|
+
shell?: string[]
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export type TuiToast = {
|
|
187
|
+
variant?: "info" | "success" | "warning" | "error"
|
|
188
|
+
title?: string
|
|
189
|
+
message: string
|
|
190
|
+
duration?: number
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export type TuiThemeCurrent = {
|
|
194
|
+
readonly primary: RGBA
|
|
195
|
+
readonly secondary: RGBA
|
|
196
|
+
readonly accent: RGBA
|
|
197
|
+
readonly error: RGBA
|
|
198
|
+
readonly warning: RGBA
|
|
199
|
+
readonly success: RGBA
|
|
200
|
+
readonly info: RGBA
|
|
201
|
+
readonly text: RGBA
|
|
202
|
+
readonly textMuted: RGBA
|
|
203
|
+
readonly selectedListItemText: RGBA
|
|
204
|
+
readonly background: RGBA
|
|
205
|
+
readonly backgroundPanel: RGBA
|
|
206
|
+
readonly backgroundElement: RGBA
|
|
207
|
+
readonly backgroundMenu: RGBA
|
|
208
|
+
readonly border: RGBA
|
|
209
|
+
readonly borderActive: RGBA
|
|
210
|
+
readonly borderSubtle: RGBA
|
|
211
|
+
readonly diffAdded: RGBA
|
|
212
|
+
readonly diffRemoved: RGBA
|
|
213
|
+
readonly diffContext: RGBA
|
|
214
|
+
readonly diffHunkHeader: RGBA
|
|
215
|
+
readonly diffHighlightAdded: RGBA
|
|
216
|
+
readonly diffHighlightRemoved: RGBA
|
|
217
|
+
readonly diffAddedBg: RGBA
|
|
218
|
+
readonly diffRemovedBg: RGBA
|
|
219
|
+
readonly diffContextBg: RGBA
|
|
220
|
+
readonly diffLineNumber: RGBA
|
|
221
|
+
readonly diffAddedLineNumberBg: RGBA
|
|
222
|
+
readonly diffRemovedLineNumberBg: RGBA
|
|
223
|
+
readonly markdownText: RGBA
|
|
224
|
+
readonly markdownHeading: RGBA
|
|
225
|
+
readonly markdownLink: RGBA
|
|
226
|
+
readonly markdownLinkText: RGBA
|
|
227
|
+
readonly markdownCode: RGBA
|
|
228
|
+
readonly markdownBlockQuote: RGBA
|
|
229
|
+
readonly markdownEmph: RGBA
|
|
230
|
+
readonly markdownStrong: RGBA
|
|
231
|
+
readonly markdownHorizontalRule: RGBA
|
|
232
|
+
readonly markdownListItem: RGBA
|
|
233
|
+
readonly markdownListEnumeration: RGBA
|
|
234
|
+
readonly markdownImage: RGBA
|
|
235
|
+
readonly markdownImageText: RGBA
|
|
236
|
+
readonly markdownCodeBlock: RGBA
|
|
237
|
+
readonly syntaxComment: RGBA
|
|
238
|
+
readonly syntaxKeyword: RGBA
|
|
239
|
+
readonly syntaxFunction: RGBA
|
|
240
|
+
readonly syntaxVariable: RGBA
|
|
241
|
+
readonly syntaxString: RGBA
|
|
242
|
+
readonly syntaxNumber: RGBA
|
|
243
|
+
readonly syntaxType: RGBA
|
|
244
|
+
readonly syntaxOperator: RGBA
|
|
245
|
+
readonly syntaxPunctuation: RGBA
|
|
246
|
+
readonly thinkingOpacity: number
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export type TuiTheme = {
|
|
250
|
+
readonly current: TuiThemeCurrent
|
|
251
|
+
readonly selected: string
|
|
252
|
+
has: (name: string) => boolean
|
|
253
|
+
set: (name: string) => boolean
|
|
254
|
+
install: (jsonPath: string) => Promise<void>
|
|
255
|
+
mode: () => "dark" | "light"
|
|
256
|
+
readonly ready: boolean
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export type TuiKV = {
|
|
260
|
+
get: <Value = unknown>(key: string, fallback?: Value) => Value
|
|
261
|
+
set: (key: string, value: unknown) => void
|
|
262
|
+
readonly ready: boolean
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export type TuiState = {
|
|
266
|
+
readonly ready: boolean
|
|
267
|
+
readonly config: SdkConfig
|
|
268
|
+
readonly provider: ReadonlyArray<Provider>
|
|
269
|
+
readonly path: {
|
|
270
|
+
state: string
|
|
271
|
+
config: string
|
|
272
|
+
worktree: string
|
|
273
|
+
directory: string
|
|
274
|
+
}
|
|
275
|
+
readonly vcs: { branch?: string } | undefined
|
|
276
|
+
session: {
|
|
277
|
+
count: () => number
|
|
278
|
+
diff: (sessionID: string) => ReadonlyArray<TuiSidebarFileItem>
|
|
279
|
+
todo: (sessionID: string) => ReadonlyArray<TuiSidebarTodoItem>
|
|
280
|
+
task: (sessionID: string) => ReadonlyArray<TuiSidebarTaskItem>
|
|
281
|
+
messages: (sessionID: string) => ReadonlyArray<Message>
|
|
282
|
+
status: (sessionID: string) => SessionStatus | undefined
|
|
283
|
+
goal: (sessionID: string) => TuiSidebarGoal | undefined
|
|
284
|
+
cwd: (sessionID: string) => string | undefined
|
|
285
|
+
permission: (sessionID: string) => ReadonlyArray<PermissionRequest>
|
|
286
|
+
question: (sessionID: string) => ReadonlyArray<QuestionRequest>
|
|
287
|
+
}
|
|
288
|
+
part: (messageID: string) => ReadonlyArray<Part>
|
|
289
|
+
lsp: () => ReadonlyArray<TuiSidebarLspItem>
|
|
290
|
+
mcp: () => ReadonlyArray<TuiSidebarMcpItem>
|
|
291
|
+
instructions: () => ReadonlyArray<string>
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
type TuiConfigView = Pick<PluginConfig, "$schema" | "theme" | "keybinds" | "plugin"> &
|
|
295
|
+
NonNullable<PluginConfig["tui"]> & {
|
|
296
|
+
plugin_enabled?: Record<string, boolean>
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export type TuiApp = {
|
|
300
|
+
readonly version: string
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
type Frozen<Value> = Value extends (...args: never[]) => unknown
|
|
304
|
+
? Value
|
|
305
|
+
: Value extends ReadonlyArray<infer Item>
|
|
306
|
+
? ReadonlyArray<Frozen<Item>>
|
|
307
|
+
: Value extends object
|
|
308
|
+
? { readonly [Key in keyof Value]: Frozen<Value[Key]> }
|
|
309
|
+
: Value
|
|
310
|
+
|
|
311
|
+
export type TuiSidebarMcpItem = {
|
|
312
|
+
name: string
|
|
313
|
+
status: McpStatus["status"]
|
|
314
|
+
error?: string
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
export type TuiSidebarLspItem = Pick<LspStatus, "id" | "root" | "status">
|
|
318
|
+
|
|
319
|
+
export type TuiSidebarGoalVerdict = {
|
|
320
|
+
ok: boolean
|
|
321
|
+
impossible?: boolean
|
|
322
|
+
reason: string
|
|
323
|
+
attempt: number
|
|
324
|
+
error?: boolean
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export type TuiSidebarGoal = {
|
|
328
|
+
condition?: string
|
|
329
|
+
verdicts: { [messageID: string]: TuiSidebarGoalVerdict }
|
|
330
|
+
lastMessageID?: string
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
export type TuiSidebarTodoItem = Pick<Todo, "content" | "status">
|
|
334
|
+
|
|
335
|
+
export type TuiSidebarTaskItem = Pick<
|
|
336
|
+
SessionTaskResponse[number],
|
|
337
|
+
"id" | "status" | "summary" | "owner" | "ended_at"
|
|
338
|
+
>
|
|
339
|
+
|
|
340
|
+
export type TuiSidebarFileItem = {
|
|
341
|
+
file: string
|
|
342
|
+
additions: number
|
|
343
|
+
deletions: number
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export type TuiHostSlotMap = {
|
|
347
|
+
app: {}
|
|
348
|
+
home_logo: {}
|
|
349
|
+
home_prompt: {
|
|
350
|
+
workspace_id?: string
|
|
351
|
+
ref?: (ref: TuiPromptRef | undefined) => void
|
|
352
|
+
}
|
|
353
|
+
home_prompt_right: {
|
|
354
|
+
workspace_id?: string
|
|
355
|
+
}
|
|
356
|
+
session_prompt: {
|
|
357
|
+
session_id: string
|
|
358
|
+
visible?: boolean
|
|
359
|
+
disabled?: boolean
|
|
360
|
+
on_submit?: () => void
|
|
361
|
+
ref?: (ref: TuiPromptRef | undefined) => void
|
|
362
|
+
}
|
|
363
|
+
session_prompt_right: {
|
|
364
|
+
session_id: string
|
|
365
|
+
}
|
|
366
|
+
home_bottom: {}
|
|
367
|
+
home_footer: {}
|
|
368
|
+
sidebar_title: {
|
|
369
|
+
session_id: string
|
|
370
|
+
title: string
|
|
371
|
+
share_url?: string
|
|
372
|
+
}
|
|
373
|
+
sidebar_content: {
|
|
374
|
+
session_id: string
|
|
375
|
+
}
|
|
376
|
+
sidebar_footer: {
|
|
377
|
+
session_id: string
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
export type TuiSlotMap<Slots extends Record<string, object> = {}> = TuiHostSlotMap & Slots
|
|
382
|
+
|
|
383
|
+
type TuiSlotShape<Name extends string, Slots extends Record<string, object>> = Name extends keyof TuiHostSlotMap
|
|
384
|
+
? TuiHostSlotMap[Name]
|
|
385
|
+
: Name extends keyof Slots
|
|
386
|
+
? Slots[Name]
|
|
387
|
+
: Record<string, unknown>
|
|
388
|
+
|
|
389
|
+
export type TuiSlotProps<Name extends string = string, Slots extends Record<string, object> = {}> = {
|
|
390
|
+
name: Name
|
|
391
|
+
mode?: SlotMode
|
|
392
|
+
children?: JSX.Element
|
|
393
|
+
} & TuiSlotShape<Name, Slots>
|
|
394
|
+
|
|
395
|
+
export type TuiSlotContext = {
|
|
396
|
+
theme: TuiTheme
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
type SlotCore<Slots extends Record<string, object> = {}> = SolidPlugin<TuiSlotMap<Slots>, TuiSlotContext>
|
|
400
|
+
|
|
401
|
+
export type TuiSlotPlugin<Slots extends Record<string, object> = {}> = Omit<SlotCore<Slots>, "id"> & {
|
|
402
|
+
id?: never
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
export type TuiSlots = {
|
|
406
|
+
register: {
|
|
407
|
+
(plugin: TuiSlotPlugin): string
|
|
408
|
+
<Slots extends Record<string, object>>(plugin: TuiSlotPlugin<Slots>): string
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
export type TuiEventBus = {
|
|
413
|
+
on: <Type extends Event["type"]>(type: Type, handler: (event: Extract<Event, { type: Type }>) => void) => () => void
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
export type TuiDispose = () => void | Promise<void>
|
|
417
|
+
|
|
418
|
+
export type TuiLifecycle = {
|
|
419
|
+
readonly signal: AbortSignal
|
|
420
|
+
onDispose: (fn: TuiDispose) => () => void
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
export type TuiPluginState = "first" | "updated" | "same"
|
|
424
|
+
|
|
425
|
+
export type TuiPluginEntry = {
|
|
426
|
+
id: string
|
|
427
|
+
source: "file" | "npm" | "internal"
|
|
428
|
+
spec: string
|
|
429
|
+
target: string
|
|
430
|
+
requested?: string
|
|
431
|
+
version?: string
|
|
432
|
+
modified?: number
|
|
433
|
+
first_time: number
|
|
434
|
+
last_time: number
|
|
435
|
+
time_changed: number
|
|
436
|
+
load_count: number
|
|
437
|
+
fingerprint: string
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
export type TuiPluginMeta = TuiPluginEntry & {
|
|
441
|
+
state: TuiPluginState
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
export type TuiPluginStatus = {
|
|
445
|
+
id: string
|
|
446
|
+
source: TuiPluginEntry["source"]
|
|
447
|
+
spec: string
|
|
448
|
+
target: string
|
|
449
|
+
enabled: boolean
|
|
450
|
+
active: boolean
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
export type TuiPluginInstallOptions = {
|
|
454
|
+
global?: boolean
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export type TuiPluginInstallResult =
|
|
458
|
+
| {
|
|
459
|
+
ok: true
|
|
460
|
+
dir: string
|
|
461
|
+
tui: boolean
|
|
462
|
+
}
|
|
463
|
+
| {
|
|
464
|
+
ok: false
|
|
465
|
+
message: string
|
|
466
|
+
missing?: boolean
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
export type TuiWorkspace = {
|
|
470
|
+
current: () => string | undefined
|
|
471
|
+
set: (workspaceID?: string) => void
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
export type TuiPluginApi = {
|
|
475
|
+
app: TuiApp
|
|
476
|
+
command: {
|
|
477
|
+
register: (cb: () => TuiCommand[]) => () => void
|
|
478
|
+
trigger: (value: string) => void
|
|
479
|
+
show: () => void
|
|
480
|
+
}
|
|
481
|
+
route: {
|
|
482
|
+
register: (routes: TuiRouteDefinition[]) => () => void
|
|
483
|
+
navigate: (name: string, params?: Record<string, unknown>) => void
|
|
484
|
+
readonly current: TuiRouteCurrent
|
|
485
|
+
}
|
|
486
|
+
ui: {
|
|
487
|
+
Dialog: (props: TuiDialogProps) => JSX.Element
|
|
488
|
+
DialogAlert: (props: TuiDialogAlertProps) => JSX.Element
|
|
489
|
+
DialogConfirm: (props: TuiDialogConfirmProps) => JSX.Element
|
|
490
|
+
DialogPrompt: (props: TuiDialogPromptProps) => JSX.Element
|
|
491
|
+
DialogSelect: <Value = unknown>(props: TuiDialogSelectProps<Value>) => JSX.Element
|
|
492
|
+
Slot: <Name extends string>(props: TuiSlotProps<Name>) => JSX.Element | null
|
|
493
|
+
Prompt: (props: TuiPromptProps) => JSX.Element
|
|
494
|
+
toast: (input: TuiToast) => void
|
|
495
|
+
dialog: TuiDialogStack
|
|
496
|
+
}
|
|
497
|
+
keybind: {
|
|
498
|
+
match: (key: string, evt: ParsedKey) => boolean
|
|
499
|
+
print: (key: string) => string
|
|
500
|
+
create: (defaults: TuiKeybindMap, overrides?: Record<string, unknown>) => TuiKeybindSet
|
|
501
|
+
}
|
|
502
|
+
readonly tuiConfig: Frozen<TuiConfigView>
|
|
503
|
+
kv: TuiKV
|
|
504
|
+
state: TuiState
|
|
505
|
+
theme: TuiTheme
|
|
506
|
+
client: TulingcodeClient
|
|
507
|
+
event: TuiEventBus
|
|
508
|
+
renderer: CliRenderer
|
|
509
|
+
slots: TuiSlots
|
|
510
|
+
plugins: {
|
|
511
|
+
list: () => ReadonlyArray<TuiPluginStatus>
|
|
512
|
+
activate: (id: string) => Promise<boolean>
|
|
513
|
+
deactivate: (id: string) => Promise<boolean>
|
|
514
|
+
add: (spec: string) => Promise<boolean>
|
|
515
|
+
install: (spec: string, options?: TuiPluginInstallOptions) => Promise<TuiPluginInstallResult>
|
|
516
|
+
}
|
|
517
|
+
lifecycle: TuiLifecycle
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
export type TuiPlugin = (api: TuiPluginApi, options: PluginOptions | undefined, meta: TuiPluginMeta) => Promise<void>
|
|
521
|
+
|
|
522
|
+
export type TuiPluginModule = {
|
|
523
|
+
id?: string
|
|
524
|
+
tui: TuiPlugin
|
|
525
|
+
server?: never
|
|
526
|
+
}
|