kanna-code 0.40.0 → 0.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/assets/index-QcIznlNf.css +32 -0
- package/dist/client/assets/index-cYoGm0Hu.js +2638 -0
- package/dist/client/index.html +2 -2
- package/dist/export-viewer/assets/index-CGQNrnEQ.css +1 -0
- package/dist/export-viewer/index.html +2 -2
- package/package.json +1 -1
- package/src/server/local-http-servers.test.ts +57 -0
- package/src/server/local-http-servers.ts +279 -0
- package/src/server/project-quick-actions.test.ts +35 -0
- package/src/server/project-quick-actions.ts +67 -0
- package/src/server/terminal-manager.ts +12 -0
- package/src/server/ws-router.ts +34 -0
- package/src/shared/protocol.ts +20 -0
- package/dist/client/assets/index-BE426WMn.js +0 -2618
- package/dist/client/assets/index-BtWOksKc.css +0 -32
- package/dist/export-viewer/assets/index-B1qCJVBc.css +0 -1
- /package/dist/export-viewer/assets/{index-DRoGJUAU.js → index-Dg5TRbWQ.js} +0 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { mkdir } from "node:fs/promises"
|
|
2
|
+
import path from "node:path"
|
|
3
|
+
import type { ProjectQuickAction } from "../shared/protocol"
|
|
4
|
+
import { resolveLocalPath } from "./paths"
|
|
5
|
+
|
|
6
|
+
const QUICK_ACTIONS_FILE_NAME = "quick-actions.json"
|
|
7
|
+
const MAX_QUICK_ACTIONS = 50
|
|
8
|
+
const MAX_LABEL_LENGTH = 80
|
|
9
|
+
const MAX_COMMAND_LENGTH = 2_000
|
|
10
|
+
|
|
11
|
+
function getProjectQuickActionsPath(projectPath: string) {
|
|
12
|
+
return path.join(resolveLocalPath(projectPath), ".kanna", QUICK_ACTIONS_FILE_NAME)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function normalizeQuickAction(value: unknown): ProjectQuickAction | null {
|
|
16
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null
|
|
17
|
+
const record = value as Record<string, unknown>
|
|
18
|
+
const id = typeof record.id === "string" ? record.id.trim() : ""
|
|
19
|
+
const label = typeof record.label === "string" ? record.label.trim() : ""
|
|
20
|
+
const command = typeof record.command === "string" ? record.command.trim() : ""
|
|
21
|
+
if (!id || !command) return null
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
id,
|
|
25
|
+
label: (label || command).slice(0, MAX_LABEL_LENGTH),
|
|
26
|
+
command: command.slice(0, MAX_COMMAND_LENGTH),
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function normalizeQuickActions(value: unknown): ProjectQuickAction[] {
|
|
31
|
+
const rawActions = Array.isArray(value)
|
|
32
|
+
? value
|
|
33
|
+
: value && typeof value === "object" && Array.isArray((value as { quickActions?: unknown }).quickActions)
|
|
34
|
+
? (value as { quickActions: unknown[] }).quickActions
|
|
35
|
+
: []
|
|
36
|
+
const seenIds = new Set<string>()
|
|
37
|
+
const actions: ProjectQuickAction[] = []
|
|
38
|
+
|
|
39
|
+
for (const rawAction of rawActions) {
|
|
40
|
+
const action = normalizeQuickAction(rawAction)
|
|
41
|
+
if (!action || seenIds.has(action.id)) continue
|
|
42
|
+
seenIds.add(action.id)
|
|
43
|
+
actions.push(action)
|
|
44
|
+
if (actions.length >= MAX_QUICK_ACTIONS) break
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return actions
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export async function readProjectQuickActions(projectPath: string): Promise<ProjectQuickAction[]> {
|
|
51
|
+
const file = Bun.file(getProjectQuickActionsPath(projectPath))
|
|
52
|
+
if (!(await file.exists())) return []
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
return normalizeQuickActions(JSON.parse(await file.text()))
|
|
56
|
+
} catch {
|
|
57
|
+
return []
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export async function writeProjectQuickActions(projectPath: string, quickActions: ProjectQuickAction[]): Promise<ProjectQuickAction[]> {
|
|
62
|
+
const filePath = getProjectQuickActionsPath(projectPath)
|
|
63
|
+
const normalized = normalizeQuickActions(quickActions)
|
|
64
|
+
await mkdir(path.dirname(filePath), { recursive: true })
|
|
65
|
+
await Bun.write(filePath, `${JSON.stringify({ quickActions: normalized }, null, 2)}\n`)
|
|
66
|
+
return normalized
|
|
67
|
+
}
|
|
@@ -327,6 +327,18 @@ export class TerminalManager {
|
|
|
327
327
|
}
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
+
getRootPidsByCwd(cwd: string) {
|
|
331
|
+
const pids: number[] = []
|
|
332
|
+
for (const session of this.sessions.values()) {
|
|
333
|
+
if (session.cwd !== cwd || session.status !== "running") continue
|
|
334
|
+
const pid = session.process?.pid
|
|
335
|
+
if (typeof pid === "number") {
|
|
336
|
+
pids.push(pid)
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return pids
|
|
340
|
+
}
|
|
341
|
+
|
|
330
342
|
private snapshotOf(session: TerminalSession): TerminalSnapshot {
|
|
331
343
|
return {
|
|
332
344
|
terminalId: session.terminalId,
|
package/src/server/ws-router.ts
CHANGED
|
@@ -14,7 +14,9 @@ import { DiffStore } from "./diff-store"
|
|
|
14
14
|
import { EventStore } from "./event-store"
|
|
15
15
|
import { openExternal } from "./external-open"
|
|
16
16
|
import { KeybindingsManager } from "./keybindings"
|
|
17
|
+
import { killLocalHttpServer, listLocalHttpServers } from "./local-http-servers"
|
|
17
18
|
import { ensureProjectDirectory, resolveLocalPath } from "./paths"
|
|
19
|
+
import { readProjectQuickActions, writeProjectQuickActions } from "./project-quick-actions"
|
|
18
20
|
import { writeStandaloneTranscriptExport } from "./standalone-export"
|
|
19
21
|
import { TerminalManager } from "./terminal-manager"
|
|
20
22
|
import type { UpdateManager } from "./update-manager"
|
|
@@ -1037,6 +1039,38 @@ export function createWsRouter({
|
|
|
1037
1039
|
send(ws, { v: PROTOCOL_VERSION, type: "ack", id })
|
|
1038
1040
|
return
|
|
1039
1041
|
}
|
|
1042
|
+
case "browser.listLocalHttpServers": {
|
|
1043
|
+
const project = command.projectId ? store.getProject(command.projectId) : null
|
|
1044
|
+
const result = await listLocalHttpServers({
|
|
1045
|
+
projectPath: project?.localPath,
|
|
1046
|
+
projectTerminalRootPids: project ? terminals.getRootPidsByCwd(project.localPath) : [],
|
|
1047
|
+
})
|
|
1048
|
+
send(ws, { v: PROTOCOL_VERSION, type: "ack", id, result })
|
|
1049
|
+
return
|
|
1050
|
+
}
|
|
1051
|
+
case "browser.killLocalHttpServer": {
|
|
1052
|
+
const result = await killLocalHttpServer(command.port)
|
|
1053
|
+
send(ws, { v: PROTOCOL_VERSION, type: "ack", id, result })
|
|
1054
|
+
return
|
|
1055
|
+
}
|
|
1056
|
+
case "project.readQuickActions": {
|
|
1057
|
+
const project = store.getProject(command.projectId)
|
|
1058
|
+
if (!project) {
|
|
1059
|
+
throw new Error("Project not found")
|
|
1060
|
+
}
|
|
1061
|
+
const result = await readProjectQuickActions(project.localPath)
|
|
1062
|
+
send(ws, { v: PROTOCOL_VERSION, type: "ack", id, result })
|
|
1063
|
+
return
|
|
1064
|
+
}
|
|
1065
|
+
case "project.writeQuickActions": {
|
|
1066
|
+
const project = store.getProject(command.projectId)
|
|
1067
|
+
if (!project) {
|
|
1068
|
+
throw new Error("Project not found")
|
|
1069
|
+
}
|
|
1070
|
+
const result = await writeProjectQuickActions(project.localPath, command.quickActions)
|
|
1071
|
+
send(ws, { v: PROTOCOL_VERSION, type: "ack", id, result })
|
|
1072
|
+
return
|
|
1073
|
+
}
|
|
1040
1074
|
case "update.check": {
|
|
1041
1075
|
const snapshot = updateManager
|
|
1042
1076
|
? await updateManager.checkForUpdates({ force: command.force })
|
package/src/shared/protocol.ts
CHANGED
|
@@ -25,6 +25,22 @@ export interface EditorOpenSettings {
|
|
|
25
25
|
commandTemplate: string
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
export interface LocalHttpServerInfo {
|
|
29
|
+
title: string
|
|
30
|
+
address: string
|
|
31
|
+
port: number
|
|
32
|
+
status: number
|
|
33
|
+
ownerPath?: string
|
|
34
|
+
processName?: string
|
|
35
|
+
sameProject?: boolean
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ProjectQuickAction {
|
|
39
|
+
id: string
|
|
40
|
+
label: string
|
|
41
|
+
command: string
|
|
42
|
+
}
|
|
43
|
+
|
|
28
44
|
export type SubscriptionTopic =
|
|
29
45
|
| { type: "sidebar" }
|
|
30
46
|
| { type: "local-projects" }
|
|
@@ -61,6 +77,10 @@ export type ClientCommand =
|
|
|
61
77
|
| { type: "sidebar.reorderProjectGroups"; projectIds: string[] }
|
|
62
78
|
| { type: "project.readDiffPatch"; projectId: string; path: string }
|
|
63
79
|
| { type: "system.ping" }
|
|
80
|
+
| { type: "browser.listLocalHttpServers"; projectId?: string }
|
|
81
|
+
| { type: "browser.killLocalHttpServer"; port: number }
|
|
82
|
+
| { type: "project.readQuickActions"; projectId: string }
|
|
83
|
+
| { type: "project.writeQuickActions"; projectId: string; quickActions: ProjectQuickAction[] }
|
|
64
84
|
| { type: "update.check"; force?: boolean }
|
|
65
85
|
| { type: "update.install" }
|
|
66
86
|
| { type: "settings.readKeybindings" }
|