@cuongtran001/kanna 1.76.2 → 1.76.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.
- package/dist/client/assets/{BoardsPage-BvYUo0PD.js → BoardsPage-DCh9hj51.js} +1 -1
- package/dist/client/assets/{BoardsRoutePage-D5hLNJ2q.js → BoardsRoutePage-DPw5ve6w.js} +1 -1
- package/dist/client/assets/ChatPage-CEeRSI6r.js +93 -0
- package/dist/client/assets/{CronJobRow-VCv0jyI2.js → CronJobRow-D2ex-2ZV.js} +1 -1
- package/dist/client/assets/{CronJobsPage-8FE4cO2q.js → CronJobsPage-BGk_HGOZ.js} +1 -1
- package/dist/client/assets/{FilePreviewSheet-B5b8L-4e.js → FilePreviewSheet-BnQeVNHq.js} +2 -2
- package/dist/client/assets/{FlowSurface-DmNZQO7Z.js → FlowSurface-RRPSX4vy.js} +1 -1
- package/dist/client/assets/{GenUIBlock-DX1nLbtf.js → GenUIBlock-DKGMRQmN.js} +2 -2
- package/dist/client/assets/{KannaSocketProvider-CiuKyRYE.js → KannaSocketProvider-CNmZYIUz.js} +1 -1
- package/dist/client/assets/{LocalProjectsPage-DjCZmQ8c.js → LocalProjectsPage-Dr5JrPMN.js} +1 -1
- package/dist/client/assets/SettingsPage-Bhy_51Vm.js +13 -0
- package/dist/client/assets/{StackBoardsRoutePage-i7WMqsk0.js → StackBoardsRoutePage-B-O5uIvz.js} +1 -1
- package/dist/client/assets/{ToolCallMessage-BhxowUjs.js → ToolCallMessage-C8Z9pIBo.js} +1 -1
- package/dist/client/assets/{VChartSurface-DQ6HIQXe.js → VChartSurface-C_LuezMZ.js} +1 -1
- package/dist/client/assets/{WorkflowsPage-BCIsFa6f.js → WorkflowsPage-BmGlYGWF.js} +1 -1
- package/dist/client/assets/{WorkflowsSection-B5TkVqRA.js → WorkflowsSection-SjENofEr.js} +1 -1
- package/dist/client/assets/{chart-renderer-DQLdORyQ.js → chart-renderer-Ce4S2Bew.js} +1 -1
- package/dist/client/assets/{chatSounds-CUN4vZG0.js → chatSounds-ih86yh5r.js} +1 -1
- package/dist/client/assets/chevron-left-DZQr0sRY.js +1 -0
- package/dist/client/assets/{clipboard.adapter-BvW6oQa_.js → clipboard.adapter-BLu7Xx3Q.js} +1 -1
- package/dist/client/assets/{columnStyle-C0IvZxLY.js → columnStyle-CXivQEvf.js} +1 -1
- package/dist/client/assets/{contextWindow-WJUHfP_d.js → contextWindow-Cpz1HmWo.js} +1 -1
- package/dist/client/assets/copyFeedbackStore-NslkB2Ap.js +1 -0
- package/dist/client/assets/{createScopedStore-DW4wfjbM.js → createScopedStore-CZBfIcri.js} +1 -1
- package/dist/client/assets/{dist-Q8elClTa.js → dist-DHxwilnY.js} +1 -1
- package/dist/client/assets/{ellipsis-D_1qLZbX.js → ellipsis-Ba-nFhTR.js} +1 -1
- package/dist/client/assets/{flow-kinds-Df0GmP61.js → flow-kinds-BIh-hHN9.js} +1 -1
- package/dist/client/assets/{folder-UHukK2MD.js → folder-B34crHxE.js} +1 -1
- package/dist/client/assets/{formatDuration-BA1K5CFs.js → formatDuration-JKx5LBF4.js} +1 -1
- package/dist/client/assets/{genui-CZI72r1O.js → genui-DmCmYDHH.js} +1 -1
- package/dist/client/assets/{globe-CQI7GjsK.js → globe-DV73QVTP.js} +1 -1
- package/dist/client/assets/{host-C0p_56Re.js → host-FY7xgVKG.js} +1 -1
- package/dist/client/assets/index-BYus2o1t.css +1 -0
- package/dist/client/assets/{index-3lHvRekg.js → index-MU4WHdaY.js} +3 -3
- package/dist/client/assets/{info-BXzVPePc.js → info-COBF8Hkz.js} +1 -1
- package/dist/client/assets/{input-BerPPEIs.js → input-BJRDZBOh.js} +1 -1
- package/dist/client/assets/{lexicalToReact-DdXqoi0d.js → lexicalToReact-BVHTqlu5.js} +3 -3
- package/dist/client/assets/{log-7fGlFSON.js → log-7NXJbErN.js} +1 -1
- package/dist/client/assets/{monitor-BOFtyQiW.js → monitor-Wl8GxNgR.js} +1 -1
- package/dist/client/assets/{pendingActionsStore-idc6m2Ya.js → pendingActionsStore-DDpYeRNm.js} +1 -1
- package/dist/client/assets/{play-DltDjX9H.js → play-CmxvHVzO.js} +1 -1
- package/dist/client/assets/{plus-CwWMJ0a-.js → plus-C3QbbvBk.js} +1 -1
- package/dist/client/assets/{popover-gn1uvc-1.js → popover-Dm-pdC4M.js} +1 -1
- package/dist/client/assets/{pushClient-NeXrldi-.js → pushClient-COMO42mb.js} +1 -1
- package/dist/client/assets/runDetached-mjGecpjX.js +1 -0
- package/dist/client/assets/{segmented-control-3UDSwswP.js → segmented-control-CfauwRtX.js} +1 -1
- package/dist/client/assets/{select-Df67vheJ.js → select-7zTZH1xA.js} +1 -1
- package/dist/client/assets/{settings-header-button-CKZHCdXh.js → settings-header-button-TMNvLQQs.js} +1 -1
- package/dist/client/assets/{sidebarPendingActions-B8iNQJfE.js → sidebarPendingActions-Bd_2oNH_.js} +1 -1
- package/dist/client/assets/{square-pen-DJjPW4f4.js → square-pen-BB5GlYSZ.js} +1 -1
- package/dist/client/assets/{state-mark-CU2hw5D9.js → state-mark-x5ennY81.js} +1 -1
- package/dist/client/assets/{terminal-8Bxl5uZh.js → terminal-D5pfyUjC.js} +1 -1
- package/dist/client/assets/{timer.adapter-BD7zwXEm.js → timer.adapter-C5oNrWbM.js} +1 -1
- package/dist/client/assets/{tools-Lo2VrFmM.js → tools-BlXGwwwh.js} +1 -1
- package/dist/client/assets/{triangle-alert-CQwDyl4K.js → triangle-alert-BwAIBaGG.js} +1 -1
- package/dist/client/assets/{useAppGlobalState-uP5C1BG8.js → useAppGlobalState-BL9aCLak.js} +1 -1
- package/dist/client/assets/{useKannaState-B2eDC-Dw.js → useKannaState-DTILzHBb.js} +1 -1
- package/dist/client/assets/{useTheme-B_JDh31l.js → useTheme-9knhPtrR.js} +1 -1
- package/dist/client/index.html +34 -34
- package/package.json +1 -1
- package/src/server/agent-coordinator-types.ts +1 -0
- package/src/server/agent-coordinator.ts +4 -0
- package/src/server/beacon-mention-prompt.test.ts +33 -0
- package/src/server/beacon-mention-prompt.ts +33 -0
- package/src/server/beacon-registry.test.ts +1 -0
- package/src/server/beacon-registry.ts +9 -1
- package/src/server/beacon-services.test.ts +11 -1
- package/src/server/beacon-services.ts +4 -0
- package/src/server/beacon-settings.test.ts +74 -1
- package/src/server/beacon-settings.ts +54 -3
- package/src/server/claude-turn-starter-types.ts +3 -0
- package/src/server/claude-turn-starter.test.ts +85 -0
- package/src/server/claude-turn-starter.ts +5 -1
- package/src/server/kanna-mcp-beacon-transfer.test.ts +1 -0
- package/src/server/kanna-mcp-beacon.test.ts +4 -1
- package/src/server/kanna-mcp-beacon.ts +16 -5
- package/src/server/push/push-manager.test.ts +39 -0
- package/src/server/push/push-manager.ts +45 -1
- package/src/server/server.ts +1 -0
- package/src/server/ws-router-broadcast.ts +1 -1
- package/src/server/ws-router-envelope.ts +2 -0
- package/src/server/ws-router-settings.test.ts +1 -0
- package/src/server/ws-router.test.ts +68 -0
- package/src/shared/beacon-alias.test.ts +64 -0
- package/src/shared/beacon-alias.ts +120 -0
- package/src/shared/beacon-config.ts +2 -0
- package/src/shared/beacon-status.test.ts +2 -0
- package/src/shared/beacon-status.ts +2 -0
- package/src/shared/chat-activity.ts +8 -0
- package/dist/client/assets/ChatPage-zfy8nznW.js +0 -93
- package/dist/client/assets/SettingsPage-ELjbPQEw.js +0 -13
- package/dist/client/assets/chevron-left-DpI8tMxJ.js +0 -1
- package/dist/client/assets/copyFeedbackStore-BsjXKW0-.js +0 -1
- package/dist/client/assets/index-D8o_YX_z.css +0 -1
- package/dist/client/assets/runDetached-BWsF_7Xo.js +0 -1
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { BeaconConfig } from "./beacon-config"
|
|
2
|
+
|
|
3
|
+
export const BEACON_ALIAS_PATTERN = /^[a-z0-9][a-z0-9_-]{0,39}$/
|
|
4
|
+
|
|
5
|
+
export const BEACON_ALIAS_MAX_LENGTH = 40
|
|
6
|
+
|
|
7
|
+
export const BEACON_MENTION_PREFIX = "beacon/"
|
|
8
|
+
|
|
9
|
+
export const BEACON_MENTION_PATTERN = "(^|[\\s\\n\\t])@beacon/([A-Za-z0-9][A-Za-z0-9_-]*)"
|
|
10
|
+
|
|
11
|
+
export function createBeaconMentionRegex(): RegExp {
|
|
12
|
+
return new RegExp(BEACON_MENTION_PATTERN, "g")
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function validateBeaconAliasFormat(alias: string): string | null {
|
|
16
|
+
if (alias.length === 0) return "Short name is required"
|
|
17
|
+
if (alias.length > BEACON_ALIAS_MAX_LENGTH) {
|
|
18
|
+
return `Short name must be at most ${BEACON_ALIAS_MAX_LENGTH} characters`
|
|
19
|
+
}
|
|
20
|
+
if (!BEACON_ALIAS_PATTERN.test(alias)) {
|
|
21
|
+
return "Use lowercase letters, digits, - and _, starting with a letter or digit"
|
|
22
|
+
}
|
|
23
|
+
return null
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function beaconDisplayName(beacon: { alias?: string | null; label: string }): string {
|
|
27
|
+
return beacon.alias ?? beacon.label
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface MentionableBeacon {
|
|
31
|
+
id: string
|
|
32
|
+
label: string
|
|
33
|
+
alias?: string | null
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface BeaconMentionIndex {
|
|
37
|
+
handleByBeaconId: ReadonlyMap<string, string>
|
|
38
|
+
beaconIdByHandle: ReadonlyMap<string, string>
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const INVALID_HANDLE_CHARS = /[^a-z0-9_-]+/g
|
|
42
|
+
const EDGE_SEPARATORS = /^[-_]+|[-_]+$/g
|
|
43
|
+
|
|
44
|
+
function slugifyLabel(label: string): string {
|
|
45
|
+
const slug = label
|
|
46
|
+
.toLowerCase()
|
|
47
|
+
.replace(INVALID_HANDLE_CHARS, "-")
|
|
48
|
+
.replace(EDGE_SEPARATORS, "")
|
|
49
|
+
.slice(0, BEACON_ALIAS_MAX_LENGTH)
|
|
50
|
+
.replace(EDGE_SEPARATORS, "")
|
|
51
|
+
return slug.length > 0 ? slug : "beacon"
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function freeHandle(base: string, taken: ReadonlyMap<string, string>): string {
|
|
55
|
+
if (!taken.has(base)) return base
|
|
56
|
+
let suffix = 2
|
|
57
|
+
while (taken.has(`${base}-${suffix}`)) suffix += 1
|
|
58
|
+
return `${base}-${suffix}`
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function buildBeaconMentionIndex(beacons: readonly MentionableBeacon[]): BeaconMentionIndex {
|
|
62
|
+
const ordered = [...beacons].sort((left, right) => left.id.localeCompare(right.id))
|
|
63
|
+
const handleByBeaconId = new Map<string, string>()
|
|
64
|
+
const beaconIdByHandle = new Map<string, string>()
|
|
65
|
+
|
|
66
|
+
for (const beacon of ordered) {
|
|
67
|
+
if (beacon.alias === undefined || beacon.alias === null) continue
|
|
68
|
+
if (beaconIdByHandle.has(beacon.alias)) continue
|
|
69
|
+
handleByBeaconId.set(beacon.id, beacon.alias)
|
|
70
|
+
beaconIdByHandle.set(beacon.alias, beacon.id)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
for (const beacon of ordered) {
|
|
74
|
+
if (handleByBeaconId.has(beacon.id)) continue
|
|
75
|
+
const handle = freeHandle(slugifyLabel(beacon.label), beaconIdByHandle)
|
|
76
|
+
handleByBeaconId.set(beacon.id, handle)
|
|
77
|
+
beaconIdByHandle.set(handle, beacon.id)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return { handleByBeaconId, beaconIdByHandle }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function parseBeaconMentionHandles(text: string): string[] {
|
|
84
|
+
const handles: string[] = []
|
|
85
|
+
for (const match of text.matchAll(createBeaconMentionRegex())) {
|
|
86
|
+
const handle = match[2]
|
|
87
|
+
if (handle !== undefined) handles.push(handle.toLowerCase())
|
|
88
|
+
}
|
|
89
|
+
return handles
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface BeaconMentionResolution {
|
|
93
|
+
beacons: BeaconConfig[]
|
|
94
|
+
unresolvedHandles: string[]
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function resolveBeaconMentions(
|
|
98
|
+
text: string,
|
|
99
|
+
beacons: readonly BeaconConfig[],
|
|
100
|
+
): BeaconMentionResolution {
|
|
101
|
+
const handles = parseBeaconMentionHandles(text)
|
|
102
|
+
if (handles.length === 0) return { beacons: [], unresolvedHandles: [] }
|
|
103
|
+
const { beaconIdByHandle } = buildBeaconMentionIndex(beacons)
|
|
104
|
+
const byId = new Map(beacons.map((beacon) => [beacon.id, beacon]))
|
|
105
|
+
const resolved: BeaconConfig[] = []
|
|
106
|
+
const unresolvedHandles: string[] = []
|
|
107
|
+
const seen = new Set<string>()
|
|
108
|
+
for (const handle of handles) {
|
|
109
|
+
const id = beaconIdByHandle.get(handle)
|
|
110
|
+
const beacon = id === undefined ? undefined : byId.get(id)
|
|
111
|
+
if (beacon === undefined) {
|
|
112
|
+
if (!unresolvedHandles.includes(handle)) unresolvedHandles.push(handle)
|
|
113
|
+
continue
|
|
114
|
+
}
|
|
115
|
+
if (seen.has(beacon.id)) continue
|
|
116
|
+
seen.add(beacon.id)
|
|
117
|
+
resolved.push(beacon)
|
|
118
|
+
}
|
|
119
|
+
return { beacons: resolved, unresolvedHandles }
|
|
120
|
+
}
|
|
@@ -4,6 +4,7 @@ import type { BeaconScope } from "./beacon-scope"
|
|
|
4
4
|
export interface BeaconConfig {
|
|
5
5
|
id: string
|
|
6
6
|
label: string
|
|
7
|
+
alias?: string
|
|
7
8
|
publicKey: string
|
|
8
9
|
os: BeaconOs
|
|
9
10
|
scope: BeaconScope
|
|
@@ -20,6 +21,7 @@ export interface BeaconInput {
|
|
|
20
21
|
|
|
21
22
|
export interface BeaconPatch {
|
|
22
23
|
label?: string
|
|
24
|
+
alias?: string | null
|
|
23
25
|
scope?: BeaconScope
|
|
24
26
|
enabled?: boolean
|
|
25
27
|
}
|
|
@@ -28,6 +28,7 @@ describe("buildBeaconStatusRows", () => {
|
|
|
28
28
|
{
|
|
29
29
|
id: "a",
|
|
30
30
|
label: "label-a",
|
|
31
|
+
alias: null,
|
|
31
32
|
os: "linux",
|
|
32
33
|
enabled: true,
|
|
33
34
|
online: true,
|
|
@@ -39,6 +40,7 @@ describe("buildBeaconStatusRows", () => {
|
|
|
39
40
|
{
|
|
40
41
|
id: "b",
|
|
41
42
|
label: "label-b",
|
|
43
|
+
alias: null,
|
|
42
44
|
os: "windows",
|
|
43
45
|
enabled: false,
|
|
44
46
|
online: false,
|
|
@@ -4,6 +4,7 @@ import type { BeaconConfig } from "./beacon-config"
|
|
|
4
4
|
export interface BeaconStatusRow {
|
|
5
5
|
id: string
|
|
6
6
|
label: string
|
|
7
|
+
alias: string | null
|
|
7
8
|
os: BeaconOs
|
|
8
9
|
enabled: boolean
|
|
9
10
|
online: boolean
|
|
@@ -37,6 +38,7 @@ export function buildBeaconStatusRows(
|
|
|
37
38
|
return {
|
|
38
39
|
id: config.id,
|
|
39
40
|
label: config.label,
|
|
41
|
+
alias: config.alias ?? null,
|
|
40
42
|
os: config.os,
|
|
41
43
|
enabled: config.enabled,
|
|
42
44
|
online: state?.online ?? false,
|