clankie 0.2.1 → 0.2.2
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/README.md +32 -17
- package/package.json +14 -5
- package/src/agent.ts +11 -0
- package/src/channels/slack.ts +3 -1
- package/src/channels/web.ts +218 -205
- package/src/cli.ts +2 -2
- package/src/config.ts +6 -2
- package/src/daemon.ts +2 -2
- package/src/extensions/workspace-jail.ts +171 -0
- package/src/service.ts +3 -1
- package/src/sessions.ts +11 -0
- package/web-ui-dist/_shell.html +2 -2
- package/web-ui-dist/assets/{card-kSKmECr1.js → card-BUP-xovx.js} +1 -1
- package/web-ui-dist/assets/extensions-DC620Nmx.js +1 -0
- package/web-ui-dist/assets/{index-CXJ3n5rE.js → index-DurjG9O_.js} +1 -1
- package/web-ui-dist/assets/{loader-circle-C5ib508E.js → loader-circle-DbOtKfCA.js} +1 -1
- package/web-ui-dist/assets/{main-cBOaKYCP.js → main-B2sRcuyZ.js} +8 -8
- package/web-ui-dist/assets/{sessions._sessionId-BIeINoSQ.js → sessions._sessionId-BJazw9EJ.js} +1 -1
- package/web-ui-dist/assets/{settings-CO37Obvo.js → settings-Bv8oeIho.js} +1 -1
- package/web-ui-dist/assets/styles-D2oHO1JL.css +1 -0
- package/web-ui-dist/assets/extensions-CFPfugfg.js +0 -1
- package/web-ui-dist/assets/styles-BQfA8H-l.css +0 -1
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace Jail Extension
|
|
3
|
+
*
|
|
4
|
+
* Restricts agent file/command access to the workspace directory.
|
|
5
|
+
* Prevents the agent from reading, writing, or executing commands
|
|
6
|
+
* that reference paths outside the configured workspace.
|
|
7
|
+
*
|
|
8
|
+
* Uses pi's tool_call event to intercept and validate all tool calls.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
12
|
+
import { isAbsolute, normalize, resolve } from "node:path";
|
|
13
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Create a workspace jail extension that restricts file access.
|
|
17
|
+
*
|
|
18
|
+
* @param workspaceDir - Absolute path to the workspace directory
|
|
19
|
+
* @param allowedPaths - Additional paths outside workspace that should be permitted
|
|
20
|
+
*/
|
|
21
|
+
export function createWorkspaceJailExtension(workspaceDir: string, allowedPaths: string[] = []) {
|
|
22
|
+
// Normalize workspace path and ensure it ends with /
|
|
23
|
+
const normalizedWorkspace = `${normalize(workspaceDir).replace(/\/$/, "")}/`;
|
|
24
|
+
|
|
25
|
+
// Normalize allowed paths (resolve to absolute, real paths where they exist)
|
|
26
|
+
const normalizedAllowedPaths = allowedPaths.map((p) => {
|
|
27
|
+
const resolved = resolve(p);
|
|
28
|
+
try {
|
|
29
|
+
return existsSync(resolved) ? realpathSync(resolved) : resolved;
|
|
30
|
+
} catch {
|
|
31
|
+
return resolved;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
return function workspaceJail(pi: ExtensionAPI) {
|
|
36
|
+
/**
|
|
37
|
+
* Check if a path is within the workspace or allowed paths.
|
|
38
|
+
* Handles symlinks, relative paths, ~ expansion, etc.
|
|
39
|
+
*/
|
|
40
|
+
function isPathAllowed(inputPath: string): { allowed: boolean; reason?: string } {
|
|
41
|
+
// Resolve to absolute path
|
|
42
|
+
let absolutePath: string;
|
|
43
|
+
|
|
44
|
+
// Handle ~ expansion
|
|
45
|
+
if (inputPath.startsWith("~/")) {
|
|
46
|
+
return { allowed: false, reason: "Access to home directory (~/) is blocked" };
|
|
47
|
+
}
|
|
48
|
+
if (inputPath === "~") {
|
|
49
|
+
return { allowed: false, reason: "Access to home directory (~) is blocked" };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Resolve relative/absolute paths against workspace
|
|
53
|
+
absolutePath = isAbsolute(inputPath) ? inputPath : resolve(workspaceDir, inputPath);
|
|
54
|
+
|
|
55
|
+
// Resolve symlinks if the path exists
|
|
56
|
+
let realPath: string;
|
|
57
|
+
try {
|
|
58
|
+
realPath = existsSync(absolutePath) ? realpathSync(absolutePath) : absolutePath;
|
|
59
|
+
} catch {
|
|
60
|
+
// If realpathSync fails (permission denied, etc), use the absolute path
|
|
61
|
+
realPath = absolutePath;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Normalize for comparison
|
|
65
|
+
const normalized = `${normalize(realPath).replace(/\/$/, "")}/`;
|
|
66
|
+
|
|
67
|
+
// Check if within workspace
|
|
68
|
+
if (normalized.startsWith(normalizedWorkspace)) {
|
|
69
|
+
return { allowed: true };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Check if within allowed paths
|
|
73
|
+
for (const allowedPath of normalizedAllowedPaths) {
|
|
74
|
+
const normalizedAllowed = `${normalize(allowedPath).replace(/\/$/, "")}/`;
|
|
75
|
+
if (normalized.startsWith(normalizedAllowed)) {
|
|
76
|
+
return { allowed: true };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
allowed: false,
|
|
82
|
+
reason: `Access denied: path '${inputPath}' is outside workspace (${workspaceDir})`,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Scan a bash command for obvious path escapes.
|
|
88
|
+
* This is defense-in-depth, not a complete sandbox.
|
|
89
|
+
*/
|
|
90
|
+
function scanBashCommand(command: string): { allowed: boolean; reason?: string } {
|
|
91
|
+
// Block absolute paths outside workspace
|
|
92
|
+
const absolutePathPattern = /(?:^|\s)([~/][\w\-./]+)/g;
|
|
93
|
+
let match: RegExpExecArray | null;
|
|
94
|
+
|
|
95
|
+
// biome-ignore lint/suspicious/noAssignInExpressions: regex exec pattern
|
|
96
|
+
while ((match = absolutePathPattern.exec(command)) !== null) {
|
|
97
|
+
const pathLike = match[1];
|
|
98
|
+
|
|
99
|
+
// Check if it looks like a path to a sensitive location
|
|
100
|
+
if (
|
|
101
|
+
pathLike.startsWith("/etc") ||
|
|
102
|
+
pathLike.startsWith("/var") ||
|
|
103
|
+
pathLike.startsWith("/usr") ||
|
|
104
|
+
pathLike.startsWith("/sys") ||
|
|
105
|
+
pathLike.startsWith("/proc") ||
|
|
106
|
+
pathLike.startsWith("/root") ||
|
|
107
|
+
pathLike.startsWith("~/")
|
|
108
|
+
) {
|
|
109
|
+
return {
|
|
110
|
+
allowed: false,
|
|
111
|
+
reason: `Blocked: command references path outside workspace: ${pathLike}`,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Block cd to absolute paths outside workspace
|
|
117
|
+
if (/\bcd\s+\//.test(command)) {
|
|
118
|
+
return { allowed: false, reason: "Blocked: 'cd /' or 'cd /path' outside workspace" };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Block obvious .. traversal attempts that escape workspace
|
|
122
|
+
// This is heuristic - catches patterns like "cd ../../.." but won't catch all evasion
|
|
123
|
+
const dotsPattern = /(?:^|\s)cd\s+(?:\.\.\/){3,}/;
|
|
124
|
+
if (dotsPattern.test(command)) {
|
|
125
|
+
return {
|
|
126
|
+
allowed: false,
|
|
127
|
+
reason: "Blocked: command attempts to traverse outside workspace using '..'",
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return { allowed: true };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Intercept all tool calls
|
|
135
|
+
pi.on("tool_call", async (event) => {
|
|
136
|
+
const { toolName, input } = event;
|
|
137
|
+
|
|
138
|
+
// File tools: validate the 'path' parameter
|
|
139
|
+
if (["read", "write", "edit", "grep", "find", "ls"].includes(toolName)) {
|
|
140
|
+
const toolInput = input as { path?: string };
|
|
141
|
+
if (toolInput.path) {
|
|
142
|
+
const check = isPathAllowed(toolInput.path);
|
|
143
|
+
if (!check.allowed) {
|
|
144
|
+
return { block: true, reason: check.reason };
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Bash: scan command for obvious path escapes
|
|
150
|
+
if (toolName === "bash") {
|
|
151
|
+
const toolInput = input as { command?: string };
|
|
152
|
+
if (toolInput.command) {
|
|
153
|
+
const check = scanBashCommand(toolInput.command);
|
|
154
|
+
if (!check.allowed) {
|
|
155
|
+
return { block: true, reason: check.reason };
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return undefined;
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Inject system prompt reminder
|
|
164
|
+
pi.on("before_agent_start", async () => {
|
|
165
|
+
return {
|
|
166
|
+
systemPrompt: `\n\nIMPORTANT: You are restricted to working within the directory: ${workspaceDir}
|
|
167
|
+
Do not access files, run commands, or reference paths outside this directory.`,
|
|
168
|
+
};
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
}
|
package/src/service.ts
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
*
|
|
9
9
|
* On Linux: installs a systemd user service (~/.config/systemd/user/clankie.service)
|
|
10
10
|
* On macOS: installs a launchd user agent (~/Library/LaunchAgents/ai.clankie.daemon.plist)
|
|
11
|
+
*
|
|
12
|
+
* Note: Requires Node 24+ for native TypeScript execution.
|
|
11
13
|
*/
|
|
12
14
|
|
|
13
15
|
import { execSync } from "node:child_process";
|
|
@@ -37,7 +39,7 @@ function resolveProgramArguments(): string[] {
|
|
|
37
39
|
// Compiled binary
|
|
38
40
|
return [process.argv[0], "start", "--foreground"];
|
|
39
41
|
}
|
|
40
|
-
// Running from source with
|
|
42
|
+
// Running from source with Node.js (TypeScript files)
|
|
41
43
|
return [process.argv[0], process.argv[1], "start", "--foreground"];
|
|
42
44
|
}
|
|
43
45
|
|
package/src/sessions.ts
CHANGED
|
@@ -14,11 +14,13 @@ import {
|
|
|
14
14
|
type CreateAgentSessionResult,
|
|
15
15
|
createAgentSession,
|
|
16
16
|
DefaultResourceLoader,
|
|
17
|
+
type ExtensionFactory,
|
|
17
18
|
ModelRegistry,
|
|
18
19
|
SessionManager,
|
|
19
20
|
} from "@mariozechner/pi-coding-agent";
|
|
20
21
|
import type { Attachment } from "./channels/channel.ts";
|
|
21
22
|
import { type AppConfig, getAgentDir, getAppDir, getAuthPath, getWorkspace } from "./config.ts";
|
|
23
|
+
import { createWorkspaceJailExtension } from "./extensions/workspace-jail.ts";
|
|
22
24
|
|
|
23
25
|
// ─── Session cache (one session per chat) ──────────────────────────────────────
|
|
24
26
|
|
|
@@ -47,9 +49,18 @@ export async function getOrCreateSession(chatKey: string, config: AppConfig): Pr
|
|
|
47
49
|
const authStorage = AuthStorage.create(getAuthPath());
|
|
48
50
|
const modelRegistry = new ModelRegistry(authStorage);
|
|
49
51
|
|
|
52
|
+
// Build extension factories (workspace jail if enabled)
|
|
53
|
+
const extensionFactories: ExtensionFactory[] = [];
|
|
54
|
+
const restrictToWorkspace = config.agent?.restrictToWorkspace ?? true; // default: enabled
|
|
55
|
+
if (restrictToWorkspace) {
|
|
56
|
+
const allowedPaths = config.agent?.allowedPaths ?? [];
|
|
57
|
+
extensionFactories.push(createWorkspaceJailExtension(cwd, allowedPaths));
|
|
58
|
+
}
|
|
59
|
+
|
|
50
60
|
const loader = new DefaultResourceLoader({
|
|
51
61
|
cwd,
|
|
52
62
|
agentDir,
|
|
63
|
+
extensionFactories,
|
|
53
64
|
});
|
|
54
65
|
await loader.reload();
|
|
55
66
|
|
package/web-ui-dist/_shell.html
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
<!DOCTYPE html><html lang="en" class="dark"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>clankie — Web UI</title><link rel="modulepreload" href="/assets/main-cBOaKYCP.js"/><link rel="modulepreload" href="/assets/index-CXJ3n5rE.js"/><link rel="stylesheet" href="/assets/styles-BQfA8H-l.css"/></head><body><div data-slot="sidebar-wrapper" style="--sidebar-width:16rem;--sidebar-width-icon:3rem" class="group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full"><div class="group peer text-sidebar-foreground hidden md:block" data-state="expanded" data-collapsible="" data-variant="inset" data-side="left" data-slot="sidebar"><div data-slot="sidebar-gap" class="transition-[width] duration-200 ease-linear relative w-(--sidebar-width) bg-transparent group-data-[collapsible=offcanvas]:w-0 group-data-[side=right]:rotate-180 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]"></div><div data-slot="sidebar-container" data-side="left" class="fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear data-[side=left]:left-0 data-[side=left]:group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)] data-[side=right]:right-0 data-[side=right]:group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)] md:flex p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]"><div data-sidebar="sidebar" data-slot="sidebar-inner" class="bg-sidebar group-data-[variant=floating]:ring-sidebar-border group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1 flex size-full flex-col"><div data-slot="sidebar-header" data-sidebar="header" class="gap-2 p-2 flex flex-col"><ul data-slot="sidebar-menu" data-sidebar="menu" class="gap-0 flex w-full min-w-0 flex-col"><li data-slot="sidebar-menu-item" data-sidebar="menu-item" class="group/menu-item relative"><a data-slot="sidebar-menu-button" data-sidebar="menu-button" data-size="lg" class="ring-sidebar-ring active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground gap-2 rounded-md p-2 text-left transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! focus-visible:ring-2 data-active:font-medium peer/menu-button flex w-full items-center overflow-hidden outline-hidden group/menu-button disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground h-12 text-sm group-data-[collapsible=icon]:p-0! active" href="/" data-status="active" aria-current="page"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-message-square size-5" aria-hidden="true"><path d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"></path></svg><span class="text-base font-semibold">clankie</span></a></li></ul></div><div data-slot="sidebar-content" data-sidebar="content" class="no-scrollbar gap-0 flex min-h-0 flex-1 flex-col overflow-auto group-data-[collapsible=icon]:overflow-hidden"><div data-slot="sidebar-group" data-sidebar="group" class="p-2 relative flex w-full min-w-0 flex-col"><div data-slot="sidebar-group-content" data-sidebar="group-content" class="text-sm w-full"><ul data-slot="sidebar-menu" data-sidebar="menu" class="gap-0 flex w-full min-w-0 flex-col"><li data-slot="sidebar-menu-item" data-sidebar="menu-item" class="group/menu-item relative"><button type="button" id="base-ui-_R_6qb6_" data-slot="sidebar-menu-button" data-sidebar="menu-button" data-size="default" class="ring-sidebar-ring data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground gap-2 rounded-md p-2 text-left transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! focus-visible:ring-2 data-active:font-medium peer/menu-button flex w-full items-center overflow-hidden outline-hidden group/menu-button disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&_svg]:size-4 [&_svg]:shrink-0 h-8 text-sm bg-primary text-primary-foreground hover:bg-primary/90 hover:text-primary-foreground active:bg-primary/90 active:text-primary-foreground duration-200 ease-linear"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle-plus" aria-hidden="true"><circle cx="12" cy="12" r="10"></circle><path d="M8 12h8"></path><path d="M12 8v8"></path></svg><span>Create Chat</span></button></li></ul></div></div><div data-slot="sidebar-group" data-sidebar="group" class="p-2 relative flex w-full min-w-0 flex-col group-data-[collapsible=icon]:hidden"><div data-slot="sidebar-group-label" data-sidebar="group-label" class="text-sidebar-foreground/70 ring-sidebar-ring h-8 rounded-md px-2 text-xs font-medium transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 flex shrink-0 items-center outline-hidden [&>svg]:shrink-0">Recent Sessions</div><ul data-slot="sidebar-menu" data-sidebar="menu" class="gap-0 flex w-full min-w-0 flex-col"><li data-slot="sidebar-menu-item" data-sidebar="menu-item" class="group/menu-item relative"><button type="button" data-slot="sidebar-menu-button" data-sidebar="menu-button" data-size="default" class="ring-sidebar-ring active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground gap-2 rounded-md p-2 text-left transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! focus-visible:ring-2 data-active:font-medium peer/menu-button flex w-full items-center overflow-hidden outline-hidden group/menu-button disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground h-8 text-sm" disabled=""><span class="text-sidebar-foreground/70">No sessions yet</span></button></li></ul></div><div data-slot="sidebar-group" data-sidebar="group" class="p-2 relative flex w-full min-w-0 flex-col mt-auto"><div data-slot="sidebar-group-content" data-sidebar="group-content" class="text-sm w-full"><ul data-slot="sidebar-menu" data-sidebar="menu" class="gap-0 flex w-full min-w-0 flex-col"><li data-slot="sidebar-menu-item" data-sidebar="menu-item" class="group/menu-item relative"><a data-slot="sidebar-menu-button" data-sidebar="menu-button" data-size="default" href="/settings" class="ring-sidebar-ring active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground gap-2 rounded-md p-2 text-left transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! focus-visible:ring-2 data-active:font-medium peer/menu-button flex w-full items-center overflow-hidden outline-hidden group/menu-button disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground h-8 text-sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-settings" aria-hidden="true"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915"></path><circle cx="12" cy="12" r="3"></circle></svg><span>Settings</span></a></li><li data-slot="sidebar-menu-item" data-sidebar="menu-item" class="group/menu-item relative"><a data-slot="sidebar-menu-button" data-sidebar="menu-button" data-size="default" href="/extensions" class="ring-sidebar-ring active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground gap-2 rounded-md p-2 text-left transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! focus-visible:ring-2 data-active:font-medium peer/menu-button flex w-full items-center overflow-hidden outline-hidden group/menu-button disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground h-8 text-sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-puzzle" aria-hidden="true"><path d="M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z"></path></svg><span>Extensions</span></a></li><li data-slot="sidebar-menu-item" data-sidebar="menu-item" class="group/menu-item relative"><div class="px-2 py-1.5"><span data-slot="badge" data-variant="secondary" class="h-5 gap-1 rounded-4xl border px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-3! inline-flex items-center whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive overflow-hidden group/badge [a]:hover:bg-secondary/80 bg-red-500/10 text-red-500 border-red-500/20 w-full justify-start"><div class="size-2 rounded-full mr-2 bg-red-500"></div>Disconnected</span></div></li></ul></div></div></div></div></div></div><main data-slot="sidebar-inset" class="bg-background md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2 relative flex w-full flex-1 flex-col"><div class="flex flex-1 flex-col overflow-hidden"><header class="flex h-14 shrink-0 items-center gap-2 border-b px-4"><button type="button" tabindex="0" data-slot="sidebar-trigger" data-sidebar="trigger" class="focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-panel-left" aria-hidden="true"><rect width="18" height="18" x="3" y="3" rx="2"></rect><path d="M9 3v18"></path></svg><span class="sr-only">Toggle Sidebar</span></button></header><!--$--><!--$--><!--/$--><script></script><!--/$--></div></main></div><script class="$tsr" id="$tsr-stream-barrier">(self.$R=self.$R||{})["tsr"]=[];self.$_TSR={h(){this.hydrated=!0,this.c()},e(){this.streamEnded=!0,this.c()},c(){this.hydrated&&this.streamEnded&&(delete self.$_TSR,delete self.$R.tsr)},p(e){this.initialized?e():this.buffer.push(e)},buffer:[]};
|
|
2
|
-
;$_TSR.router=($R=>$R[0]={manifest:$R[1]={routes:$R[2]={__root__:$R[3]={preloads:$R[4]=["/assets/main-
|
|
1
|
+
<!DOCTYPE html><html lang="en" class="dark"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>clankie — Web UI</title><link rel="modulepreload" href="/assets/main-B2sRcuyZ.js"/><link rel="modulepreload" href="/assets/index-DurjG9O_.js"/><link rel="stylesheet" href="/assets/styles-D2oHO1JL.css"/></head><body><div data-slot="sidebar-wrapper" style="--sidebar-width:16rem;--sidebar-width-icon:3rem" class="group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full"><div class="group peer text-sidebar-foreground hidden md:block" data-state="expanded" data-collapsible="" data-variant="inset" data-side="left" data-slot="sidebar"><div data-slot="sidebar-gap" class="transition-[width] duration-200 ease-linear relative w-(--sidebar-width) bg-transparent group-data-[collapsible=offcanvas]:w-0 group-data-[side=right]:rotate-180 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]"></div><div data-slot="sidebar-container" data-side="left" class="fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear data-[side=left]:left-0 data-[side=left]:group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)] data-[side=right]:right-0 data-[side=right]:group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)] md:flex p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]"><div data-sidebar="sidebar" data-slot="sidebar-inner" class="bg-sidebar group-data-[variant=floating]:ring-sidebar-border group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1 flex size-full flex-col"><div data-slot="sidebar-header" data-sidebar="header" class="gap-2 p-2 flex flex-col"><ul data-slot="sidebar-menu" data-sidebar="menu" class="gap-0 flex w-full min-w-0 flex-col"><li data-slot="sidebar-menu-item" data-sidebar="menu-item" class="group/menu-item relative"><a data-slot="sidebar-menu-button" data-sidebar="menu-button" data-size="lg" class="ring-sidebar-ring active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground gap-2 rounded-md p-2 text-left transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! focus-visible:ring-2 data-active:font-medium peer/menu-button flex w-full items-center overflow-hidden outline-hidden group/menu-button disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground h-12 text-sm group-data-[collapsible=icon]:p-0! active" href="/" data-status="active" aria-current="page"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-message-square size-5" aria-hidden="true"><path d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"></path></svg><span class="text-base font-semibold">clankie</span></a></li></ul></div><div data-slot="sidebar-content" data-sidebar="content" class="no-scrollbar gap-0 flex min-h-0 flex-1 flex-col overflow-auto group-data-[collapsible=icon]:overflow-hidden"><div data-slot="sidebar-group" data-sidebar="group" class="p-2 relative flex w-full min-w-0 flex-col"><div data-slot="sidebar-group-content" data-sidebar="group-content" class="text-sm w-full"><ul data-slot="sidebar-menu" data-sidebar="menu" class="gap-0 flex w-full min-w-0 flex-col"><li data-slot="sidebar-menu-item" data-sidebar="menu-item" class="group/menu-item relative"><button type="button" id="base-ui-_R_6qb6_" data-slot="sidebar-menu-button" data-sidebar="menu-button" data-size="default" class="ring-sidebar-ring data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground gap-2 rounded-md p-2 text-left transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! focus-visible:ring-2 data-active:font-medium peer/menu-button flex w-full items-center overflow-hidden outline-hidden group/menu-button disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&_svg]:size-4 [&_svg]:shrink-0 h-8 text-sm bg-primary text-primary-foreground hover:bg-primary/90 hover:text-primary-foreground active:bg-primary/90 active:text-primary-foreground duration-200 ease-linear"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle-plus" aria-hidden="true"><circle cx="12" cy="12" r="10"></circle><path d="M8 12h8"></path><path d="M12 8v8"></path></svg><span>Create Chat</span></button></li></ul></div></div><div data-slot="sidebar-group" data-sidebar="group" class="p-2 relative flex w-full min-w-0 flex-col group-data-[collapsible=icon]:hidden"><div data-slot="sidebar-group-label" data-sidebar="group-label" class="text-sidebar-foreground/70 ring-sidebar-ring h-8 rounded-md px-2 text-xs font-medium transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 flex shrink-0 items-center outline-hidden [&>svg]:shrink-0">Recent Sessions</div><ul data-slot="sidebar-menu" data-sidebar="menu" class="gap-0 flex w-full min-w-0 flex-col"><li data-slot="sidebar-menu-item" data-sidebar="menu-item" class="group/menu-item relative"><button type="button" data-slot="sidebar-menu-button" data-sidebar="menu-button" data-size="default" class="ring-sidebar-ring active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground gap-2 rounded-md p-2 text-left transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! focus-visible:ring-2 data-active:font-medium peer/menu-button flex w-full items-center overflow-hidden outline-hidden group/menu-button disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground h-8 text-sm" disabled=""><span class="text-sidebar-foreground/70">No sessions yet</span></button></li></ul></div><div data-slot="sidebar-group" data-sidebar="group" class="p-2 relative flex w-full min-w-0 flex-col mt-auto"><div data-slot="sidebar-group-content" data-sidebar="group-content" class="text-sm w-full"><ul data-slot="sidebar-menu" data-sidebar="menu" class="gap-0 flex w-full min-w-0 flex-col"><li data-slot="sidebar-menu-item" data-sidebar="menu-item" class="group/menu-item relative"><a data-slot="sidebar-menu-button" data-sidebar="menu-button" data-size="default" href="/settings" class="ring-sidebar-ring active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground gap-2 rounded-md p-2 text-left transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! focus-visible:ring-2 data-active:font-medium peer/menu-button flex w-full items-center overflow-hidden outline-hidden group/menu-button disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground h-8 text-sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-settings" aria-hidden="true"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915"></path><circle cx="12" cy="12" r="3"></circle></svg><span>Settings</span></a></li><li data-slot="sidebar-menu-item" data-sidebar="menu-item" class="group/menu-item relative"><a data-slot="sidebar-menu-button" data-sidebar="menu-button" data-size="default" href="/extensions" class="ring-sidebar-ring active:bg-sidebar-accent active:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground gap-2 rounded-md p-2 text-left transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! focus-visible:ring-2 data-active:font-medium peer/menu-button flex w-full items-center overflow-hidden outline-hidden group/menu-button disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground h-8 text-sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-puzzle" aria-hidden="true"><path d="M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z"></path></svg><span>Extensions</span></a></li><li data-slot="sidebar-menu-item" data-sidebar="menu-item" class="group/menu-item relative"><div class="px-2 py-1.5"><span data-slot="badge" data-variant="secondary" class="h-5 gap-1 rounded-4xl border px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-3! inline-flex items-center whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive overflow-hidden group/badge [a]:hover:bg-secondary/80 bg-red-500/10 text-red-500 border-red-500/20 w-full justify-start"><div class="size-2 rounded-full mr-2 bg-red-500"></div>Disconnected</span></div></li></ul></div></div></div></div></div></div><main data-slot="sidebar-inset" class="bg-background md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2 relative flex w-full flex-1 flex-col"><div class="flex flex-1 flex-col overflow-hidden"><header class="flex h-14 shrink-0 items-center gap-2 border-b px-4"><button type="button" tabindex="0" data-slot="sidebar-trigger" data-sidebar="trigger" class="focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-panel-left" aria-hidden="true"><rect width="18" height="18" x="3" y="3" rx="2"></rect><path d="M9 3v18"></path></svg><span class="sr-only">Toggle Sidebar</span></button></header><!--$--><!--$--><!--/$--><script></script><!--/$--></div></main></div><script class="$tsr" id="$tsr-stream-barrier">(self.$R=self.$R||{})["tsr"]=[];self.$_TSR={h(){this.hydrated=!0,this.c()},e(){this.streamEnded=!0,this.c()},c(){this.hydrated&&this.streamEnded&&(delete self.$_TSR,delete self.$R.tsr)},p(e){this.initialized?e():this.buffer.push(e)},buffer:[]};
|
|
2
|
+
;$_TSR.router=($R=>$R[0]={manifest:$R[1]={routes:$R[2]={__root__:$R[3]={preloads:$R[4]=["/assets/main-B2sRcuyZ.js"],assets:$R[5]=[$R[6]={tag:"script",attrs:$R[7]={type:"module",async:!0},children:"import(\"/assets/main-B2sRcuyZ.js\")"}]}}},matches:$R[8]=[$R[9]={i:"__root__",u:1772120693090,s:"success",ssr:!0}],lastMatchId:"__root__"})($R["tsr"]);$_TSR.e();document.currentScript.remove()</script><script type="module" async="">import("/assets/main-B2sRcuyZ.js")</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as K,r,N as u,C as Y,E as D,F as G,a as Q,G as L,H as C,I as W,J as $,K as q,M as A,O as X,Q as Z,R as ee,j as b,f as h,T as te}from"./main-
|
|
1
|
+
import{c as K,r,N as u,C as Y,E as D,F as G,a as Q,G as L,H as C,I as W,J as $,K as q,M as A,O as X,Q as Z,R as ee,j as b,f as h,T as te}from"./main-B2sRcuyZ.js";const ae=[["path",{d:"M21.801 10A10 10 0 1 1 17 3.335",key:"yps3ct"}],["path",{d:"m9 11 3 3L22 4",key:"1pflzl"}]],he=K("circle-check-big",ae);let j=(function(e){return e.disabled="data-disabled",e.valid="data-valid",e.invalid="data-invalid",e.touched="data-touched",e.dirty="data-dirty",e.filled="data-filled",e.focused="data-focused",e})({});const le={badInput:!1,customError:!1,patternMismatch:!1,rangeOverflow:!1,rangeUnderflow:!1,stepMismatch:!1,tooLong:!1,tooShort:!1,typeMismatch:!1,valid:null,valueMissing:!1},re={valid(e){return e===null?null:e?{[j.valid]:""}:{[j.invalid]:""}}},ne=r.createContext({invalid:void 0,name:void 0,validityData:{state:le,errors:[],error:"",value:"",initialValue:null},setValidityData:u,disabled:void 0,touched:!1,setTouched:u,dirty:!1,setDirty:u,filled:!1,setFilled:u,focused:!1,setFocused:u,validate:()=>null,validationMode:"onSubmit",validationDebounceTime:0,shouldValidateOnChange:()=>!1,state:{disabled:!1,valid:null,touched:!1,dirty:!1,filled:!1,focused:!1},markedDirtyRef:{current:!1},validation:{getValidationProps:(e=D)=>e,getInputValidationProps:(e=D)=>e,inputRef:{current:null},commit:async()=>{}}});function P(e=!0){const t=r.useContext(ne);if(t.setValidityData===u&&!e)throw new Error(Y(28));return t}const ie=r.createContext({formRef:{current:{fields:new Map}},errors:{},clearErrors:u,validationMode:"onSubmit",submitAttemptedRef:{current:!1}});function de(){return r.useContext(ie)}const se=r.createContext({controlId:void 0,registerControlId:u,labelId:void 0,setLabelId:u,messageIds:[],setMessageIds:u,getDescriptionProps:e=>e});function S(){return r.useContext(se)}function oe(e,t){return{...e,state:{...e.state,valid:!t&&e.state.valid}}}function ue({controlled:e,default:t,name:a,state:c="value"}){const{current:v}=r.useRef(e!==void 0),[d,s]=r.useState(t),l=v?e:d,p=r.useCallback(m=>{v||s(m)},[]);return[l,p]}function ce(e={}){const{id:t,implicit:a=!1,controlRef:c}=e,{controlId:v,registerControlId:d}=S(),s=G(t),l=a?v:void 0,p=Q(()=>Symbol("labelable-control")),m=r.useRef(!1),g=r.useRef(t!=null),o=L(()=>{!m.current||d===u||(m.current=!1,d(p.current,void 0))});return C(()=>{if(d===u)return;let n;if(a){const i=c?.current;W(i)&&i.closest("label")!=null?n=t??null:n=l??s}else if(t!=null)g.current=!0,n=t;else if(g.current)n=s;else{o();return}if(n===void 0){o();return}m.current=!0,d(p.current,n)},[t,c,l,d,a,s,p,o]),r.useEffect(()=>o,[o]),v??s}function fe(e){const{enabled:t=!0,value:a,id:c,name:v,controlRef:d,commit:s}=e,{formRef:l}=de(),{invalid:p,markedDirtyRef:m,validityData:g,setValidityData:o}=P(),n=L(e.getValue);C(()=>{if(!t)return;let i=a;i===void 0&&(i=n()),g.initialValue===null&&i!==null&&o(y=>({...y,initialValue:i}))},[t,o,a,g.initialValue,n]),C(()=>{!t||!c||l.current.fields.set(c,{getValue:n,name:v,controlRef:d,validityData:oe(g,p),validate(i=!0){let y=a;y===void 0&&(y=n()),m.current=!0,i?$.flushSync(()=>s(y)):s(y)}})},[s,d,t,l,n,c,p,m,v,g,a]),C(()=>{const i=l.current.fields;return()=>{c&&i.delete(c)}},[l,c])}const pe=r.forwardRef(function(t,a){const{render:c,className:v,id:d,name:s,value:l,disabled:p=!1,onValueChange:m,defaultValue:g,autoFocus:o=!1,...n}=t,{state:i,name:y,disabled:z,setTouched:E,setDirty:_,validityData:O,setFocused:I,setFilled:R,validationMode:U,validation:x}=P(),k=z||p,N=y??s,B={...i,disabled:k},{labelId:H}=S(),T=ce({id:d});C(()=>{const f=l!=null;x.inputRef.current?.value||f&&l!==""?R(!0):f&&l===""&&R(!1)},[x.inputRef,R,l]);const w=r.useRef(null);C(()=>{o&&w.current===q(A(w.current))&&I(!0)},[o,I]);const[J]=ue({controlled:l,default:g,name:"FieldControl",state:"value"}),F=l!==void 0,M=F?J:void 0;return fe({id:T,name:N,commit:x.commit,value:M,getValue:()=>x.inputRef.current?.value,controlRef:x.inputRef}),X("input",t,{ref:[a,w],state:B,props:[{id:T,disabled:k,name:N,ref:x.inputRef,"aria-labelledby":H,autoFocus:o,...F?{value:M}:{defaultValue:g},onChange(f){const V=f.currentTarget.value;m?.(V,Z(ee,f.nativeEvent)),_(V!==O.initialValue),R(V!=="")},onFocus(){I(!0)},onBlur(f){E(!0),I(!1),U==="onBlur"&&x.commit(f.currentTarget.value)},onKeyDown(f){f.currentTarget.tagName==="INPUT"&&f.key==="Enter"&&(E(!0),x.commit(f.currentTarget.value))}},x.getInputValidationProps(),n],stateAttributesMapping:re})}),me=r.forwardRef(function(t,a){return b.jsx(pe,{ref:a,...t})});function ye({className:e,type:t,...a}){return b.jsx(me,{type:t,"data-slot":"input",className:h("dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-input/50 dark:disabled:bg-input/80 h-8 rounded-lg border bg-transparent px-2.5 py-1 text-base transition-colors file:h-6 file:text-sm file:font-medium focus-visible:ring-3 aria-invalid:ring-3 md:text-sm file:text-foreground placeholder:text-muted-foreground w-full min-w-0 outline-none file:inline-flex file:border-0 file:bg-transparent disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",e),...a})}function ge({className:e,...t}){return b.jsx("label",{"data-slot":"label",className:h("gap-2 text-sm leading-none font-medium group-data-[disabled=true]:opacity-50 peer-disabled:opacity-50 flex items-center select-none group-data-[disabled=true]:pointer-events-none peer-disabled:cursor-not-allowed",e),...t})}const be=te("data-[invalid=true]:text-destructive gap-2 group/field flex w-full",{variants:{orientation:{vertical:"flex-col *:w-full [&>.sr-only]:w-auto",horizontal:"flex-row items-center *:data-[slot=field-label]:flex-auto has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",responsive:"flex-col *:w-full [&>.sr-only]:w-auto @md/field-group:flex-row @md/field-group:items-center @md/field-group:*:w-auto @md/field-group:*:data-[slot=field-label]:flex-auto @md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px"}},defaultVariants:{orientation:"vertical"}});function Ce({className:e,orientation:t="vertical",...a}){return b.jsx("div",{role:"group","data-slot":"field","data-orientation":t,className:h(be({orientation:t}),e),...a})}function Ie({className:e,...t}){return b.jsx(ge,{"data-slot":"field-label",className:h("has-data-checked:bg-primary/5 has-data-checked:border-primary/30 dark:has-data-checked:border-primary/20 dark:has-data-checked:bg-primary/10 gap-2 group-data-[disabled=true]/field:opacity-50 has-[>[data-slot=field]]:rounded-lg has-[>[data-slot=field]]:border *:data-[slot=field]:p-2.5 group/field-label peer/field-label flex w-fit leading-snug","has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col",e),...t})}function Re({className:e,size:t="default",...a}){return b.jsx("div",{"data-slot":"card","data-size":t,className:h("ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-xl py-4 text-sm ring-1 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl group/card flex flex-col",e),...a})}function we({className:e,...t}){return b.jsx("div",{"data-slot":"card-header",className:h("gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]",e),...t})}function Ve({className:e,...t}){return b.jsx("div",{"data-slot":"card-title",className:h("text-base leading-snug font-medium group-data-[size=sm]/card:text-sm",e),...t})}function Ee({className:e,...t}){return b.jsx("div",{"data-slot":"card-description",className:h("text-muted-foreground text-sm",e),...t})}function ke({className:e,...t}){return b.jsx("div",{"data-slot":"card-content",className:h("px-4 group-data-[size=sm]/card:px-3",e),...t})}export{he as C,Ce as F,ye as I,Ie as a,Re as b,we as c,Ve as d,Ee as e,ke as f};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{c as w,S as T,m as u,q,w as z,r as x,p as L,j as e,L as B,B as p,A as R,P as V,y as o}from"./main-B2sRcuyZ.js";import{b as j,c as g,d as f,e as N,f as v,F as $,a as G,I as H,C as J}from"./card-BUP-xovx.js";import{L as E}from"./loader-circle-DbOtKfCA.js";const K=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12",key:"1pkeuh"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16",key:"4dfq90"}]],y=w("circle-alert",K);const O=[["path",{d:"M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z",key:"1a0edw"}],["path",{d:"M12 22V12",key:"d0xqtd"}],["polyline",{points:"3.29 7 12 12 20.71 7",key:"ousv84"}],["path",{d:"m7.5 4.27 9 5.15",key:"1c824w"}]],P=w("package",O);const Q=[["path",{d:"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",key:"1s2grr"}],["path",{d:"M20 2v4",key:"1rf3ol"}],["path",{d:"M22 4h-4",key:"gwowj6"}],["circle",{cx:"4",cy:"20",r:"2",key:"6kqj1y"}]],U=w("sparkles",Q),W={extensions:[],extensionErrors:[],skills:[],skillDiagnostics:[],isLoading:!1,installStatus:{isInstalling:!1,output:"",exitCode:null}},r=new T(W);function F(i){r.setState(a=>({...a,isLoading:i}))}function X(i,a){r.setState(c=>({...c,extensions:i,extensionErrors:a,isLoading:!1}))}function Y(i,a){r.setState(c=>({...c,skills:i,skillDiagnostics:a,isLoading:!1}))}function k(i){r.setState(a=>({...a,installStatus:{...a.installStatus,...i}}))}function Z(){r.setState(i=>({...i,installStatus:{isInstalling:!1,output:"",exitCode:null,error:void 0}}))}function ae(){const{status:i}=u(q,s=>({status:s.status})),{activeSessionId:a}=u(z,s=>({activeSessionId:s.activeSessionId})),{extensions:c,extensionErrors:S,skills:b,skillDiagnostics:C,isLoading:A,installStatus:n}=u(r,s=>s),[d,M]=x.useState(""),[I,_]=x.useState(!1),m=i==="connected",h=x.useCallback(async()=>{const s=L.getClient();if(!(!s||!a)){F(!0);try{await s.reload(a);const[t,l]=await Promise.all([s.getExtensions(a),s.getSkills(a)]);X(t.extensions,t.errors),Y(l.skills,l.diagnostics)}catch(t){console.error("Failed to load extensions and skills:",t),F(!1)}}},[a]);x.useEffect(()=>{m&&a&&h()},[m,a,h]);const D=async()=>{const s=L.getClient();if(!(!s||!a||!d.trim())){k({isInstalling:!0,output:"",exitCode:null,error:void 0});try{const t=await s.installPackage(a,d.trim(),I);k({isInstalling:!1,output:t.output,exitCode:t.exitCode}),t.exitCode===0&&await h()}catch(t){k({isInstalling:!1,error:t instanceof Error?t.message:String(t)})}}};return m?A?e.jsx("div",{className:"flex h-full items-center justify-center",children:e.jsxs("div",{className:"text-center space-y-2",children:[e.jsx(E,{className:"inline-block h-8 w-8 animate-spin text-primary"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Loading extensions and skills..."})]})}):e.jsx("div",{className:"h-full overflow-y-auto",children:e.jsxs("div",{className:"container max-w-4xl py-8 px-4 space-y-6",children:[e.jsxs(j,{children:[e.jsxs(g,{children:[e.jsxs(f,{className:"flex items-center gap-2",children:[e.jsx(V,{className:"h-5 w-5"}),"Extensions"]}),e.jsx(N,{children:"Loaded extensions with their registered tools and commands"})]}),e.jsxs(v,{children:[S.length>0&&e.jsx("div",{className:"mb-4 rounded-md border border-destructive/50 bg-destructive/10 p-3",children:e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx(y,{className:"h-4 w-4 text-destructive mt-0.5"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"text-sm font-medium text-destructive",children:"Extension Load Errors"}),e.jsx("div",{className:"mt-2 space-y-2",children:S.map((s,t)=>e.jsxs("div",{className:"text-xs",children:[e.jsx("p",{className:"font-mono text-muted-foreground",children:s.path}),e.jsx("p",{className:"text-destructive",children:s.error})]},t))})]})]})}),c.length===0?e.jsx("p",{className:"text-sm text-muted-foreground py-4",children:"No extensions loaded."}):e.jsx("div",{className:"space-y-3",children:c.map((s,t)=>e.jsx("div",{className:"rounded-lg border p-3",children:e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium font-mono break-all",children:s.path}),s.resolvedPath!==s.path&&e.jsxs("p",{className:"text-xs text-muted-foreground font-mono mt-1 break-all",children:["→ ",s.resolvedPath]})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[s.tools.length>0&&e.jsxs("div",{className:"flex flex-wrap gap-1",children:[e.jsx("span",{className:"text-xs text-muted-foreground mr-1",children:"Tools:"}),s.tools.map(l=>e.jsx(o,{variant:"secondary",className:"text-xs",children:l},l))]}),s.commands.length>0&&e.jsxs("div",{className:"flex flex-wrap gap-1",children:[e.jsx("span",{className:"text-xs text-muted-foreground mr-1",children:"Commands:"}),s.commands.map(l=>e.jsxs(o,{variant:"default",className:"text-xs",children:["/",l]},l))]}),s.flags.length>0&&e.jsxs("div",{className:"flex flex-wrap gap-1",children:[e.jsx("span",{className:"text-xs text-muted-foreground mr-1",children:"Flags:"}),s.flags.map(l=>e.jsxs(o,{variant:"outline",className:"text-xs",children:["--",l]},l))]}),s.shortcuts.length>0&&e.jsxs("div",{className:"flex flex-wrap gap-1",children:[e.jsx("span",{className:"text-xs text-muted-foreground mr-1",children:"Shortcuts:"}),s.shortcuts.map(l=>e.jsx(o,{variant:"outline",className:"text-xs font-mono",children:l},l))]})]})]})},t))})]})]}),e.jsxs(j,{children:[e.jsxs(g,{children:[e.jsxs(f,{className:"flex items-center gap-2",children:[e.jsx(U,{className:"h-5 w-5"}),"Skills"]}),e.jsx(N,{children:"Available skills for the agent"})]}),e.jsxs(v,{children:[C.length>0&&e.jsx("div",{className:"mb-4 rounded-md border border-yellow-500/50 bg-yellow-500/10 p-3",children:e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx(y,{className:"h-4 w-4 text-yellow-600 mt-0.5"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("p",{className:"text-sm font-medium text-yellow-600",children:"Skill Diagnostics"}),e.jsx("div",{className:"mt-2 space-y-1",children:C.map((s,t)=>e.jsxs("p",{className:"text-xs text-yellow-700",children:[s.path&&e.jsxs("span",{className:"font-mono",children:[s.path,": "]}),s.message]},t))})]})]})}),b.length===0?e.jsx("p",{className:"text-sm text-muted-foreground py-4",children:"No skills loaded."}):e.jsx("div",{className:"space-y-3",children:b.map((s,t)=>e.jsx("div",{className:"rounded-lg border p-3",children:e.jsxs("div",{className:"space-y-2",children:[e.jsx("div",{className:"flex items-start justify-between gap-2",children:e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("p",{className:"text-sm font-medium",children:s.name}),s.disableModelInvocation&&e.jsx(o,{variant:"outline",className:"text-xs",children:"Manual only"})]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:s.description})]})}),e.jsxs("div",{className:"flex flex-wrap gap-2 text-xs text-muted-foreground",children:[e.jsxs("span",{children:[e.jsx("span",{className:"font-medium",children:"Source:"})," ",s.source]}),e.jsx("span",{children:"•"}),e.jsx("span",{className:"font-mono break-all",children:s.filePath})]})]})},t))})]})]}),e.jsxs(j,{children:[e.jsxs(g,{children:[e.jsxs(f,{className:"flex items-center gap-2",children:[e.jsx(P,{className:"h-5 w-5"}),"Install Package"]}),e.jsx(N,{children:"Install a Pi package from npm, git, or a local path"})]}),e.jsxs(v,{className:"space-y-4",children:[e.jsxs($,{children:[e.jsx(G,{htmlFor:"package-source",children:"Package Source"}),e.jsx(H,{id:"package-source",type:"text",placeholder:"npm:@foo/bar@1.0.0, git:github.com/user/repo, or /path/to/package",value:d,onChange:s=>M(s.target.value),disabled:n.isInstalling}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-1",children:["Examples: ",e.jsx("code",{className:"text-xs",children:"npm:package-name"}),","," ",e.jsx("code",{className:"text-xs",children:"git:github.com/user/repo"}),","," ",e.jsx("code",{className:"text-xs",children:"/absolute/path"})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"checkbox",id:"install-local",checked:I,onChange:s=>_(s.target.checked),disabled:n.isInstalling,className:"h-4 w-4"}),e.jsx("label",{htmlFor:"install-local",className:"text-sm cursor-pointer",children:"Install to project settings (.pi/settings.json) instead of global"})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(p,{onClick:D,disabled:n.isInstalling||!d.trim(),className:"flex-1",children:n.isInstalling?e.jsxs(e.Fragment,{children:[e.jsx(E,{className:"mr-2 h-4 w-4 animate-spin"}),"Installing..."]}):e.jsxs(e.Fragment,{children:[e.jsx(P,{className:"mr-2 h-4 w-4"}),"Install"]})}),(n.output||n.error)&&e.jsx(p,{variant:"outline",onClick:Z,children:"Clear"})]}),n.error&&e.jsxs("div",{className:"rounded-md border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive",children:[e.jsx("p",{className:"font-medium",children:"Error"}),e.jsx("p",{className:"text-xs mt-1",children:n.error})]}),n.output&&e.jsxs("div",{className:"space-y-2",children:[e.jsx("div",{className:"flex items-center gap-2",children:n.exitCode===0?e.jsxs(e.Fragment,{children:[e.jsx(J,{className:"h-4 w-4 text-green-600"}),e.jsx("p",{className:"text-sm font-medium text-green-600",children:"Installation Successful"})]}):e.jsxs(e.Fragment,{children:[e.jsx(y,{className:"h-4 w-4 text-destructive"}),e.jsxs("p",{className:"text-sm font-medium text-destructive",children:["Installation Failed (exit code: ",n.exitCode,")"]})]})}),e.jsx("div",{className:"rounded-md bg-muted p-3 text-xs font-mono whitespace-pre-wrap break-all max-h-60 overflow-y-auto",children:n.output})]})]})]})]})}):e.jsx("div",{className:"flex h-full items-center justify-center",children:e.jsxs("div",{className:"text-center space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx("h2",{className:"text-2xl font-semibold",children:"Not Connected"}),e.jsx("p",{className:"text-muted-foreground",children:"Configure your connection to get started"})]}),e.jsx(B,{to:"/settings",children:e.jsxs(p,{children:[e.jsx(R,{className:"mr-2 h-4 w-4"}),"Go to Settings"]})})]})})}export{ae as component};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{U as r,m as o,q as c,w as d,r as l,j as s,L as x,B as m,A as u}from"./main-
|
|
1
|
+
import{U as r,m as o,q as c,w as d,r as l,j as s,L as x,B as m,A as u}from"./main-B2sRcuyZ.js";function j(){const i=r(),{status:a}=o(c,n=>({status:n.status})),{activeSessionId:e}=o(d,n=>({activeSessionId:n.activeSessionId})),t=a==="connected";return l.useEffect(()=>{t&&e&&(console.log(`[index] Redirecting to active session: ${e}`),i({to:"/sessions/$sessionId",params:{sessionId:e}}))},[e,t,i]),t?s.jsx("div",{className:"flex h-full items-center justify-center",children:s.jsxs("div",{className:"text-center space-y-2",children:[s.jsx("div",{className:"inline-block h-8 w-8 animate-spin rounded-full border-4 border-primary border-r-transparent"}),s.jsx("p",{className:"text-sm text-muted-foreground",children:"Loading sessions..."})]})}):s.jsx("div",{className:"flex h-full items-center justify-center",children:s.jsxs("div",{className:"text-center space-y-4",children:[s.jsxs("div",{className:"space-y-2",children:[s.jsx("h2",{className:"text-2xl font-semibold",children:"Not Connected"}),s.jsx("p",{className:"text-muted-foreground",children:"Configure your connection to get started"})]}),s.jsx(x,{to:"/settings",children:s.jsxs(m,{children:[s.jsx(u,{className:"mr-2 h-4 w-4"}),"Go to Settings"]})})]})})}export{j as component};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c}from"./main-
|
|
1
|
+
import{c}from"./main-B2sRcuyZ.js";const e=[["path",{d:"M21 12a9 9 0 1 1-6.219-8.56",key:"13zald"}]],a=c("loader-circle",e);export{a as L};
|