@castlekit/castle 0.1.5 → 0.3.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/drizzle.config.ts +7 -0
- package/next.config.ts +1 -0
- package/package.json +25 -4
- package/src/app/api/avatars/[id]/route.ts +122 -25
- package/src/app/api/openclaw/agents/[id]/avatar/route.ts +216 -0
- package/src/app/api/openclaw/agents/route.ts +77 -41
- package/src/app/api/openclaw/agents/status/route.ts +55 -0
- package/src/app/api/openclaw/chat/attachments/route.ts +230 -0
- package/src/app/api/openclaw/chat/channels/route.ts +214 -0
- package/src/app/api/openclaw/chat/route.ts +272 -0
- package/src/app/api/openclaw/chat/search/route.ts +149 -0
- package/src/app/api/openclaw/chat/storage/route.ts +75 -0
- package/src/app/api/openclaw/config/route.ts +45 -4
- package/src/app/api/openclaw/events/route.ts +31 -2
- package/src/app/api/openclaw/logs/route.ts +20 -5
- package/src/app/api/openclaw/restart/route.ts +12 -4
- package/src/app/api/openclaw/session/status/route.ts +42 -0
- package/src/app/api/settings/avatar/route.ts +190 -0
- package/src/app/api/settings/route.ts +88 -0
- package/src/app/chat/[channelId]/error-boundary.tsx +64 -0
- package/src/app/chat/[channelId]/page.tsx +305 -0
- package/src/app/chat/layout.tsx +96 -0
- package/src/app/chat/page.tsx +52 -0
- package/src/app/globals.css +89 -2
- package/src/app/layout.tsx +7 -1
- package/src/app/page.tsx +147 -28
- package/src/app/settings/page.tsx +300 -0
- package/src/cli/onboarding.ts +202 -37
- package/src/components/chat/agent-mention-popup.tsx +89 -0
- package/src/components/chat/archived-channels.tsx +190 -0
- package/src/components/chat/channel-list.tsx +140 -0
- package/src/components/chat/chat-input.tsx +310 -0
- package/src/components/chat/create-channel-dialog.tsx +171 -0
- package/src/components/chat/markdown-content.tsx +205 -0
- package/src/components/chat/message-bubble.tsx +152 -0
- package/src/components/chat/message-list.tsx +508 -0
- package/src/components/chat/message-queue.tsx +68 -0
- package/src/components/chat/session-divider.tsx +61 -0
- package/src/components/chat/session-stats-panel.tsx +139 -0
- package/src/components/chat/storage-indicator.tsx +76 -0
- package/src/components/layout/sidebar.tsx +126 -45
- package/src/components/layout/user-menu.tsx +29 -4
- package/src/components/providers/presence-provider.tsx +8 -0
- package/src/components/providers/search-provider.tsx +81 -0
- package/src/components/search/search-dialog.tsx +269 -0
- package/src/components/ui/avatar.tsx +11 -9
- package/src/components/ui/dialog.tsx +10 -4
- package/src/components/ui/tooltip.tsx +25 -8
- package/src/components/ui/twemoji-text.tsx +37 -0
- package/src/lib/api-security.ts +188 -0
- package/src/lib/config.ts +36 -4
- package/src/lib/date-utils.ts +79 -0
- package/src/lib/db/__tests__/queries.test.ts +318 -0
- package/src/lib/db/index.ts +642 -0
- package/src/lib/db/queries.ts +1017 -0
- package/src/lib/db/schema.ts +160 -0
- package/src/lib/device-identity.ts +303 -0
- package/src/lib/gateway-connection.ts +273 -36
- package/src/lib/hooks/use-agent-status.ts +251 -0
- package/src/lib/hooks/use-chat.ts +775 -0
- package/src/lib/hooks/use-openclaw.ts +105 -70
- package/src/lib/hooks/use-search.ts +113 -0
- package/src/lib/hooks/use-session-stats.ts +57 -0
- package/src/lib/hooks/use-user-settings.ts +46 -0
- package/src/lib/types/chat.ts +186 -0
- package/src/lib/types/search.ts +60 -0
- package/src/middleware.ts +52 -0
- package/vitest.config.ts +13 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Universal Search — Type System
|
|
3
|
+
// ============================================================================
|
|
4
|
+
//
|
|
5
|
+
// Discriminated union so every result carries its type and the dialog can
|
|
6
|
+
// render + navigate each type differently. Adding a new searchable content
|
|
7
|
+
// type later requires only:
|
|
8
|
+
//
|
|
9
|
+
// 1. Add a new interface extending SearchResultBase
|
|
10
|
+
// 2. Add it to the SearchResult union
|
|
11
|
+
// 3. Add a renderer in the search dialog
|
|
12
|
+
// 4. Add a search function in the API
|
|
13
|
+
//
|
|
14
|
+
// No changes to the dialog, hook, provider, keyboard shortcuts, or routing.
|
|
15
|
+
|
|
16
|
+
// --- Content type registry ---
|
|
17
|
+
|
|
18
|
+
export type SearchResultType = "message" | "task" | "note" | "project";
|
|
19
|
+
// ^ Extend this union as new content types are added
|
|
20
|
+
|
|
21
|
+
// --- Base result shape (shared fields) ---
|
|
22
|
+
|
|
23
|
+
export interface SearchResultBase {
|
|
24
|
+
id: string;
|
|
25
|
+
type: SearchResultType;
|
|
26
|
+
title: string; // Primary display text
|
|
27
|
+
subtitle?: string; // Secondary line (sender, project name, etc.)
|
|
28
|
+
snippet: string; // Content excerpt with match context
|
|
29
|
+
timestamp: number; // For sorting / display
|
|
30
|
+
href: string; // Where to navigate on click
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// --- Content-specific result types ---
|
|
34
|
+
|
|
35
|
+
export interface MessageSearchResult extends SearchResultBase {
|
|
36
|
+
type: "message";
|
|
37
|
+
channelId: string;
|
|
38
|
+
channelName: string;
|
|
39
|
+
messageId: string;
|
|
40
|
+
senderType: "user" | "agent";
|
|
41
|
+
senderName: string;
|
|
42
|
+
archived?: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Future examples (not implemented in v1):
|
|
46
|
+
// export interface TaskSearchResult extends SearchResultBase {
|
|
47
|
+
// type: "task";
|
|
48
|
+
// projectId: string;
|
|
49
|
+
// status: "todo" | "in_progress" | "done";
|
|
50
|
+
// }
|
|
51
|
+
//
|
|
52
|
+
// export interface NoteSearchResult extends SearchResultBase {
|
|
53
|
+
// type: "note";
|
|
54
|
+
// notebookId: string;
|
|
55
|
+
// }
|
|
56
|
+
|
|
57
|
+
// --- Discriminated union ---
|
|
58
|
+
|
|
59
|
+
export type SearchResult = MessageSearchResult;
|
|
60
|
+
// ^ Becomes: MessageSearchResult | TaskSearchResult | NoteSearchResult | ...
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Next.js Middleware — applies security checks to all API routes.
|
|
5
|
+
*
|
|
6
|
+
* In production, rejects requests from non-localhost IPs.
|
|
7
|
+
* Castle is a local-first app and should never be exposed to the internet.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const LOCALHOST_HOSTS = new Set([
|
|
11
|
+
"localhost",
|
|
12
|
+
"127.0.0.1",
|
|
13
|
+
"::1",
|
|
14
|
+
"::ffff:127.0.0.1",
|
|
15
|
+
]);
|
|
16
|
+
|
|
17
|
+
export function middleware(request: NextRequest) {
|
|
18
|
+
// Only enforce in production — dev is always allowed
|
|
19
|
+
if (process.env.NODE_ENV === "development") {
|
|
20
|
+
return NextResponse.next();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Check if the request originates from localhost
|
|
24
|
+
const host = request.headers.get("host") || "";
|
|
25
|
+
const hostname = host.split(":")[0];
|
|
26
|
+
|
|
27
|
+
const forwarded = request.headers.get("x-forwarded-for");
|
|
28
|
+
const clientIp = forwarded?.split(",")[0].trim();
|
|
29
|
+
|
|
30
|
+
// If x-forwarded-for is present and it's not localhost, reject
|
|
31
|
+
if (clientIp && !LOCALHOST_HOSTS.has(clientIp)) {
|
|
32
|
+
return NextResponse.json(
|
|
33
|
+
{ error: "Forbidden — Castle is only accessible from localhost" },
|
|
34
|
+
{ status: 403 }
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// If the host header isn't a localhost variant, reject
|
|
39
|
+
if (hostname && !LOCALHOST_HOSTS.has(hostname)) {
|
|
40
|
+
return NextResponse.json(
|
|
41
|
+
{ error: "Forbidden — Castle is only accessible from localhost" },
|
|
42
|
+
{ status: 403 }
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return NextResponse.next();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Only run middleware on API routes
|
|
50
|
+
export const config = {
|
|
51
|
+
matcher: "/api/:path*",
|
|
52
|
+
};
|
package/vitest.config.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { defineConfig } from "vitest/config";
|
|
2
|
+
import { resolve } from "path";
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
test: {
|
|
6
|
+
globals: true,
|
|
7
|
+
environment: "node",
|
|
8
|
+
include: ["src/**/*.test.ts", "src/**/*.test.tsx"],
|
|
9
|
+
alias: {
|
|
10
|
+
"@": resolve(__dirname, "src"),
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
});
|