clankie 0.9.0 → 0.10.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.
Files changed (26) hide show
  1. package/README.md +3 -0
  2. package/dist/cli.js +154 -35
  3. package/package.json +2 -2
  4. package/web-ui-dist/_shell.html +2 -2
  5. package/web-ui-dist/assets/{auth-B9O56j8p.js → auth-B20mIC_p.js} +1 -1
  6. package/web-ui-dist/assets/badge-3e57zy_2.js +1 -0
  7. package/web-ui-dist/assets/check-CePvKusa.js +1 -0
  8. package/web-ui-dist/assets/{circle-x-DXPT4pz6.js → circle-x-B1Pwi07a.js} +1 -1
  9. package/web-ui-dist/assets/{connection-yciJazNP.js → connection-D4rgB5k2.js} +1 -1
  10. package/web-ui-dist/assets/extensions-BxWXmCbJ.js +1 -0
  11. package/web-ui-dist/assets/{extensions-OUCiAY5C.js → extensions-Cf8QLmLt.js} +1 -1
  12. package/web-ui-dist/assets/{field-BbqZG4RJ.js → field-DfBj0pPw.js} +1 -1
  13. package/web-ui-dist/assets/{index-r9_5oSFI.js → index-Ff5WtXhh.js} +1 -1
  14. package/web-ui-dist/assets/{index-DDPzWyca.js → index-TBNB5eLy.js} +1 -1
  15. package/web-ui-dist/assets/{json-render-renderer-BcrsT8Ur.js → json-render-renderer-BrlU1n47.js} +1 -1
  16. package/web-ui-dist/assets/main-CP6prmzV.js +35 -0
  17. package/web-ui-dist/assets/{scoped-models-C9IkaHnT.js → scoped-models-DDH_ssLY.js} +1 -1
  18. package/web-ui-dist/assets/{sessions._sessionId-D9fk3HTP.js → sessions._sessionId-CWtQlITL.js} +24 -24
  19. package/web-ui-dist/assets/{skills-DYeJYRTs.js → skills-Clk3tV2m.js} +1 -1
  20. package/web-ui-dist/assets/styles-KEhqa3CU.css +1 -0
  21. package/web-ui-dist/assets/{theme-D4lx1WJW.js → theme-e79Jvep_.js} +1 -1
  22. package/web-ui-dist/assets/badge-CFXQDPlY.js +0 -1
  23. package/web-ui-dist/assets/check-D-vykl4i.js +0 -1
  24. package/web-ui-dist/assets/extensions-COhAmsTM.js +0 -1
  25. package/web-ui-dist/assets/main-D1-MPeAM.js +0 -35
  26. package/web-ui-dist/assets/styles-C4OT29Wk.css +0 -1
package/README.md CHANGED
@@ -118,6 +118,9 @@ clankie "Summarize recent git commits"
118
118
  # Check daemon status
119
119
  clankie status
120
120
 
121
+ # Update clankie and restart daemon/service if needed
122
+ clankie self-update
123
+
121
124
  # Stop daemon
122
125
  clankie stop
123
126
 
package/dist/cli.js CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from "node:module";
3
+ import { execSync, spawn, spawnSync } from "node:child_process";
3
4
  import * as crypto$2 from "node:crypto";
4
5
  import { createHash, randomBytes, randomUUID } from "node:crypto";
5
6
  import * as fs$6 from "node:fs";
@@ -14,7 +15,7 @@ import path, { basename as basename$1, dirname as dirname$1, isAbsolute as isAbs
14
15
  import { fileURLToPath } from "url";
15
16
  import * as os$2 from "node:os";
16
17
  import os, { homedir as homedir$1, platform as platform$1, tmpdir } from "node:os";
17
- import { exec, execSync, spawn, spawnSync } from "child_process";
18
+ import { exec, execSync as execSync$1, spawn as spawn$1, spawnSync as spawnSync$1 } from "child_process";
18
19
  import { Readable } from "stream";
19
20
  import crypto$1, { randomUUID as randomUUID$1 } from "crypto";
20
21
  import { createServer } from "http";
@@ -36,7 +37,6 @@ import { access as access$1, lstat, open, readFile as readFile$1, readdir as rea
36
37
  import { EventEmitter as EventEmitter$1 } from "node:events";
37
38
  import tty from "node:tty";
38
39
  import { createRequire as createRequire$1 } from "module";
39
- import { execSync as execSync$1, spawn as spawn$1, spawnSync as spawnSync$1 } from "node:child_process";
40
40
  import { StringDecoder } from "node:string_decoder";
41
41
  import { finished as finished$1 } from "stream/promises";
42
42
  import { createInterface } from "node:readline";
@@ -213478,7 +213478,7 @@ let cachedShellConfig = null;
213478
213478
  function findBashOnPath() {
213479
213479
  if (process.platform === "win32") {
213480
213480
  try {
213481
- const result = spawnSync("where", ["bash.exe"], {
213481
+ const result = spawnSync$1("where", ["bash.exe"], {
213482
213482
  encoding: "utf-8",
213483
213483
  timeout: 5e3
213484
213484
  });
@@ -213490,7 +213490,7 @@ function findBashOnPath() {
213490
213490
  return null;
213491
213491
  }
213492
213492
  try {
213493
- const result = spawnSync("which", ["bash"], {
213493
+ const result = spawnSync$1("which", ["bash"], {
213494
213494
  encoding: "utf-8",
213495
213495
  timeout: 5e3
213496
213496
  });
@@ -213601,7 +213601,7 @@ function sanitizeBinaryOutput(str) {
213601
213601
  */
213602
213602
  function killProcessTree(pid) {
213603
213603
  if (process.platform === "win32") try {
213604
- spawn("taskkill", [
213604
+ spawn$1("taskkill", [
213605
213605
  "/F",
213606
213606
  "/T",
213607
213607
  "/PID",
@@ -213822,7 +213822,7 @@ function truncateLine(line, maxChars = 500) {
213822
213822
  function executeBash(command, options) {
213823
213823
  return new Promise((resolve, reject) => {
213824
213824
  const { shell, args } = getShellConfig();
213825
- const child = spawn(shell, [...args, command], {
213825
+ const child = spawn$1(shell, [...args, command], {
213826
213826
  detached: true,
213827
213827
  env: getShellEnv(),
213828
213828
  stdio: [
@@ -263025,7 +263025,7 @@ function walkDirectoryWithFd(baseDir, fdPath, query, maxResults) {
263025
263025
  ".git/**"
263026
263026
  ];
263027
263027
  if (query) args.push(query);
263028
- const result = spawnSync(fdPath, args, {
263028
+ const result = spawnSync$1(fdPath, args, {
263029
263029
  encoding: "utf-8",
263030
263030
  stdio: [
263031
263031
  "pipe",
@@ -271480,7 +271480,7 @@ function createEventBus() {
271480
271480
  */
271481
271481
  async function execCommand(command, args, cwd, options) {
271482
271482
  return new Promise((resolve) => {
271483
- const proc = spawn$1(command, args, {
271483
+ const proc = spawn(command, args, {
271484
271484
  cwd,
271485
271485
  shell: false,
271486
271486
  stdio: [
@@ -273542,7 +273542,7 @@ const defaultBashOperations = { exec: (command, cwd, { onData, signal, timeout,
273542
273542
  reject(/* @__PURE__ */ new Error(`Working directory does not exist: ${cwd}\nCannot execute bash commands.`));
273543
273543
  return;
273544
273544
  }
273545
- const child = spawn(shell, [...args, command], {
273545
+ const child = spawn$1(shell, [...args, command], {
273546
273546
  cwd,
273547
273547
  detached: true,
273548
273548
  env: env ?? getShellEnv(),
@@ -279228,7 +279228,7 @@ const TOOLS = {
279228
279228
  };
279229
279229
  function commandExists(cmd) {
279230
279230
  try {
279231
- const result = spawnSync(cmd, ["--version"], { stdio: "pipe" });
279231
+ const result = spawnSync$1(cmd, ["--version"], { stdio: "pipe" });
279232
279232
  return result.error === void 0 || result.error === null;
279233
279233
  } catch {
279234
279234
  return false;
@@ -279289,7 +279289,7 @@ async function downloadTool(tool) {
279289
279289
  mkdirSync$1(extractDir, { recursive: true });
279290
279290
  try {
279291
279291
  if (assetName.endsWith(".tar.gz")) {
279292
- const extractResult = spawnSync("tar", [
279292
+ const extractResult = spawnSync$1("tar", [
279293
279293
  "xzf",
279294
279294
  archivePath,
279295
279295
  "-C",
@@ -279451,7 +279451,7 @@ function createFindTool(cwd, options) {
279451
279451
  } catch {}
279452
279452
  for (const gitignorePath of gitignoreFiles) args.push("--ignore-file", gitignorePath);
279453
279453
  args.push(pattern, searchPath);
279454
- const result = spawnSync(fdPath, args, {
279454
+ const result = spawnSync$1(fdPath, args, {
279455
279455
  encoding: "utf-8",
279456
279456
  maxBuffer: 10 * 1024 * 1024
279457
279457
  });
@@ -279606,7 +279606,7 @@ function createGrepTool(cwd, options) {
279606
279606
  if (literal) args.push("--fixed-strings");
279607
279607
  if (glob) args.push("--glob", glob);
279608
279608
  args.push(pattern, searchPath);
279609
- const child = spawn(rgPath, args, { stdio: [
279609
+ const child = spawn$1(rgPath, args, { stdio: [
279610
279610
  "ignore",
279611
279611
  "pipe",
279612
279612
  "pipe"
@@ -285304,7 +285304,7 @@ function executeCommand(commandConfig) {
285304
285304
  const command = commandConfig.slice(1);
285305
285305
  let result;
285306
285306
  try {
285307
- result = execSync(command, {
285307
+ result = execSync$1(command, {
285308
285308
  encoding: "utf-8",
285309
285309
  timeout: 1e4,
285310
285310
  stdio: [
@@ -289898,7 +289898,7 @@ var DefaultPackageManager = class {
289898
289898
  }
289899
289899
  runCommand(command, args, options) {
289900
289900
  return new Promise((resolvePromise, reject) => {
289901
- const child = spawn$1(command, args, {
289901
+ const child = spawn(command, args, {
289902
289902
  cwd: options?.cwd,
289903
289903
  stdio: "inherit",
289904
289904
  shell: process.platform === "win32"
@@ -289911,7 +289911,7 @@ var DefaultPackageManager = class {
289911
289911
  });
289912
289912
  }
289913
289913
  runCommandSync(command, args) {
289914
- const result = spawnSync$1(command, args, {
289914
+ const result = spawnSync(command, args, {
289915
289915
  stdio: [
289916
289916
  "ignore",
289917
289917
  "pipe",
@@ -292560,7 +292560,7 @@ var SessionList = class {
292560
292560
  * Delete a session file, trying the `trash` CLI first, then falling back to unlink
292561
292561
  */
292562
292562
  async function deleteSessionFile(sessionPath) {
292563
- const trashResult = spawnSync$1("trash", sessionPath.startsWith("-") ? ["--", sessionPath] : [sessionPath], { encoding: "utf-8" });
292563
+ const trashResult = spawnSync("trash", sessionPath.startsWith("-") ? ["--", sessionPath] : [sessionPath], { encoding: "utf-8" });
292564
292564
  const getTrashErrorHint = () => {
292565
292565
  const parts = [];
292566
292566
  if (trashResult.error) parts.push(trashResult.error.message);
@@ -293321,7 +293321,7 @@ async function convertToPng$1(bytes) {
293321
293321
  }
293322
293322
  }
293323
293323
  function runCommand(command, args, options) {
293324
- const result = spawnSync(command, args, {
293324
+ const result = spawnSync$1(command, args, {
293325
293325
  timeout: options?.timeoutMs ?? DEFAULT_READ_TIMEOUT_MS,
293326
293326
  maxBuffer: options?.maxBufferBytes ?? DEFAULT_MAX_BUFFER_BYTES
293327
293327
  });
@@ -293418,16 +293418,16 @@ function copyToClipboard(text) {
293418
293418
  timeout: 5e3
293419
293419
  };
293420
293420
  try {
293421
- if (p === "darwin") execSync("pbcopy", options);
293422
- else if (p === "win32") execSync("clip", options);
293421
+ if (p === "darwin") execSync$1("pbcopy", options);
293422
+ else if (p === "win32") execSync$1("clip", options);
293423
293423
  else {
293424
293424
  if (process.env.TERMUX_VERSION) try {
293425
- execSync("termux-clipboard-set", options);
293425
+ execSync$1("termux-clipboard-set", options);
293426
293426
  return;
293427
293427
  } catch {}
293428
293428
  if (isWaylandSession()) try {
293429
- execSync("which wl-copy", { stdio: "ignore" });
293430
- const proc = spawn("wl-copy", [], { stdio: [
293429
+ execSync$1("which wl-copy", { stdio: "ignore" });
293430
+ const proc = spawn$1("wl-copy", [], { stdio: [
293431
293431
  "pipe",
293432
293432
  "ignore",
293433
293433
  "ignore"
@@ -293438,15 +293438,15 @@ function copyToClipboard(text) {
293438
293438
  proc.unref();
293439
293439
  } catch {
293440
293440
  try {
293441
- execSync("xclip -selection clipboard", options);
293441
+ execSync$1("xclip -selection clipboard", options);
293442
293442
  } catch {
293443
- execSync("xsel --clipboard --input", options);
293443
+ execSync$1("xsel --clipboard --input", options);
293444
293444
  }
293445
293445
  }
293446
293446
  else try {
293447
- execSync("xclip -selection clipboard", options);
293447
+ execSync$1("xclip -selection clipboard", options);
293448
293448
  } catch {
293449
- execSync("xsel --clipboard --input", options);
293449
+ execSync$1("xsel --clipboard --input", options);
293450
293450
  }
293451
293451
  }
293452
293452
  } catch {}
@@ -294465,7 +294465,7 @@ var ExtensionEditorComponent = class extends Container {
294465
294465
  fs$6.writeFileSync(tmpFile, currentText, "utf-8");
294466
294466
  this.tui.stop();
294467
294467
  const [editor, ...editorArgs] = editorCmd.split(" ");
294468
- if (spawnSync$1(editor, [...editorArgs, tmpFile], { stdio: "inherit" }).status === 0) {
294468
+ if (spawnSync(editor, [...editorArgs, tmpFile], { stdio: "inherit" }).status === 0) {
294469
294469
  const newContent = fs$6.readFileSync(tmpFile, "utf-8").replace(/\n$/, "");
294470
294470
  this.editor.setText(newContent);
294471
294471
  }
@@ -298986,7 +298986,7 @@ var InteractiveMode = class InteractiveMode {
298986
298986
  fs$6.writeFileSync(tmpFile, currentText, "utf-8");
298987
298987
  this.ui.stop();
298988
298988
  const [editor, ...editorArgs] = editorCmd.split(" ");
298989
- if (spawnSync(editor, [...editorArgs, tmpFile], { stdio: "inherit" }).status === 0) {
298989
+ if (spawnSync$1(editor, [...editorArgs, tmpFile], { stdio: "inherit" }).status === 0) {
298990
298990
  const newContent = fs$6.readFileSync(tmpFile, "utf-8").replace(/\n$/, "");
298991
298991
  this.editor.setText(newContent);
298992
298992
  }
@@ -299749,7 +299749,7 @@ var InteractiveMode = class InteractiveMode {
299749
299749
  }
299750
299750
  async handleShareCommand() {
299751
299751
  try {
299752
- if (spawnSync("gh", ["auth", "status"], { encoding: "utf-8" }).status !== 0) {
299752
+ if (spawnSync$1("gh", ["auth", "status"], { encoding: "utf-8" }).status !== 0) {
299753
299753
  this.showError("GitHub CLI is not logged in. Run 'gh auth login' first.");
299754
299754
  return;
299755
299755
  }
@@ -299786,7 +299786,7 @@ var InteractiveMode = class InteractiveMode {
299786
299786
  };
299787
299787
  try {
299788
299788
  const result = await new Promise((resolve) => {
299789
- proc = spawn("gh", [
299789
+ proc = spawn$1("gh", [
299790
299790
  "gist",
299791
299791
  "create",
299792
299792
  "--public=false",
@@ -308838,7 +308838,7 @@ function execSafe(cmd) {
308838
308838
  try {
308839
308839
  return {
308840
308840
  ok: true,
308841
- stdout: execSync$1(cmd, {
308841
+ stdout: execSync(cmd, {
308842
308842
  encoding: "utf-8",
308843
308843
  stdio: [
308844
308844
  "pipe",
@@ -309027,6 +309027,51 @@ async function uninstallService() {
309027
309027
  process.exit(1);
309028
309028
  }
309029
309029
  }
309030
+ function hasInstalledService() {
309031
+ if (isMac) return existsSync(launchdPlistPath());
309032
+ if (isLinux) return existsSync(systemdUnitPath());
309033
+ return false;
309034
+ }
309035
+ function restartInstalledService() {
309036
+ if (isMac) {
309037
+ const plistPath = launchdPlistPath();
309038
+ if (!existsSync(plistPath)) {
309039
+ console.error("Clankie is not installed as a launchd agent.");
309040
+ process.exit(1);
309041
+ }
309042
+ const uid = typeof process.getuid === "function" ? process.getuid() : void 0;
309043
+ if (uid === void 0) {
309044
+ console.error("Could not determine current user ID for launchd restart.");
309045
+ process.exit(1);
309046
+ }
309047
+ if (!execSafe(`launchctl bootout gui/${uid} "${plistPath}"`).ok) execSafe(`launchctl unload "${plistPath}"`);
309048
+ const bootstrap = execSafe(`launchctl bootstrap gui/${uid} "${plistPath}"`);
309049
+ if (!bootstrap.ok) {
309050
+ const load = execSafe(`launchctl load "${plistPath}"`);
309051
+ if (!load.ok) {
309052
+ console.error(`launchctl restart failed: ${bootstrap.stderr || load.stderr}`);
309053
+ process.exit(1);
309054
+ }
309055
+ }
309056
+ console.log(`Restarted launchd agent: ${LAUNCHD_LABEL}`);
309057
+ return;
309058
+ }
309059
+ if (isLinux) {
309060
+ if (!existsSync(systemdUnitPath())) {
309061
+ console.error("Clankie is not installed as a systemd user service.");
309062
+ process.exit(1);
309063
+ }
309064
+ const restart = execSafe(`systemctl --user restart ${SERVICE_NAME}.service`);
309065
+ if (!restart.ok) {
309066
+ console.error(`systemd restart failed: ${restart.stderr || restart.stdout}`);
309067
+ process.exit(1);
309068
+ }
309069
+ console.log(`Restarted systemd service: ${SERVICE_NAME}.service`);
309070
+ return;
309071
+ }
309072
+ console.error(`Service management not supported on ${platform$1()}.`);
309073
+ process.exit(1);
309074
+ }
309030
309075
  function showServiceLogs() {
309031
309076
  if (isMac) logsLaunchd();
309032
309077
  else if (isLinux) logsSystemd();
@@ -309055,6 +309100,8 @@ function showServiceStatus() {
309055
309100
  * clankie start Start the daemon (channels + agent)
309056
309101
  * clankie stop Stop the daemon
309057
309102
  * clankie restart Restart the daemon
309103
+ * clankie update Update clankie via npm and restart daemon/service if needed
309104
+ * clankie self-update Alias for update
309058
309105
  * clankie status Check daemon status
309059
309106
  * clankie daemon install Install as a system service (systemd/launchd)
309060
309107
  * clankie daemon uninstall Remove the system service
@@ -309076,6 +309123,8 @@ Usage:
309076
309123
  clankie start [--foreground] Start the daemon (foreground by default)
309077
309124
  clankie stop Stop the daemon
309078
309125
  clankie restart Restart the daemon
309126
+ clankie update Update clankie via npm and restart daemon/service if needed
309127
+ clankie self-update Alias for update
309079
309128
  clankie status Check if daemon is running
309080
309129
  clankie daemon install Install as a system service (systemd/launchd)
309081
309130
  clankie daemon uninstall Remove the system service
@@ -309125,15 +309174,40 @@ Examples:
309125
309174
  Credentials are stored at ~/.clankie/auth.json (separate from pi's auth).
309126
309175
  `);
309127
309176
  }
309128
- function printVersion() {
309177
+ function getCurrentVersion() {
309129
309178
  const packagePath = join(import.meta.dirname, "..", "package.json");
309130
309179
  try {
309131
309180
  const pkg = JSON.parse(readFileSync(packagePath, "utf-8"));
309132
- console.log(`clankie ${pkg.version}`);
309181
+ return typeof pkg.version === "string" ? pkg.version : void 0;
309133
309182
  } catch {
309134
- console.log("clankie (version unknown)");
309183
+ return;
309135
309184
  }
309136
309185
  }
309186
+ function printVersion() {
309187
+ const version = getCurrentVersion();
309188
+ if (version) console.log(`clankie ${version}`);
309189
+ else console.log("clankie (version unknown)");
309190
+ }
309191
+ function getGlobalNpmRoot() {
309192
+ const result = spawnSync("npm", ["root", "-g"], { encoding: "utf-8" });
309193
+ if (result.status !== 0) return void 0;
309194
+ return result.stdout.trim() || void 0;
309195
+ }
309196
+ function isInstalledFromGlobalNpm() {
309197
+ const globalRoot = getGlobalNpmRoot();
309198
+ if (!globalRoot) return false;
309199
+ const packageRoot = join(import.meta.dirname, "..");
309200
+ return packageRoot === join(globalRoot, "clankie") || packageRoot.startsWith(`${join(globalRoot, "clankie")}/`);
309201
+ }
309202
+ function getLatestPublishedVersion() {
309203
+ const result = spawnSync("npm", [
309204
+ "view",
309205
+ "clankie",
309206
+ "version"
309207
+ ], { encoding: "utf-8" });
309208
+ if (result.status !== 0) return void 0;
309209
+ return result.stdout.trim() || void 0;
309210
+ }
309137
309211
  async function cmdSend(args) {
309138
309212
  const message = args.join(" ").trim();
309139
309213
  if (!message) {
@@ -309295,6 +309369,47 @@ function cmdStop() {
309295
309369
  async function cmdRestart() {
309296
309370
  await restartDaemon();
309297
309371
  }
309372
+ async function cmdUpdate() {
309373
+ const packageName = "clankie";
309374
+ const currentVersion = getCurrentVersion();
309375
+ const latestVersion = getLatestPublishedVersion();
309376
+ const serviceInstalled = hasInstalledService();
309377
+ const daemonRunning = isRunning().running;
309378
+ if (!isInstalledFromGlobalNpm()) {
309379
+ console.error("Self-update only supports npm global installs.");
309380
+ console.error("Please update clankie with the same package manager or workflow you used to install it.");
309381
+ process.exit(1);
309382
+ }
309383
+ if (currentVersion && latestVersion) {
309384
+ console.log(`Current version: ${currentVersion}`);
309385
+ console.log(`Latest version: ${latestVersion}`);
309386
+ if (currentVersion === latestVersion) {
309387
+ console.log("clankie is already up to date.");
309388
+ return;
309389
+ }
309390
+ console.log();
309391
+ } else console.log("Checking latest version via npm failed or returned no version; proceeding with update.");
309392
+ console.log(`Updating ${packageName} via npm...`);
309393
+ const update = spawnSync("npm", [
309394
+ "install",
309395
+ "-g",
309396
+ `${packageName}@latest`
309397
+ ], { stdio: "inherit" });
309398
+ if (update.status !== 0) process.exit(update.status ?? 1);
309399
+ console.log("\n✓ clankie updated.");
309400
+ if (serviceInstalled) {
309401
+ console.log("Restarting installed service...");
309402
+ restartInstalledService();
309403
+ return;
309404
+ }
309405
+ if (daemonRunning) {
309406
+ console.log("Restarting daemon with the updated CLI...");
309407
+ const restart = spawnSync("clankie", ["restart"], { stdio: "inherit" });
309408
+ if (restart.status !== 0) process.exit(restart.status ?? 1);
309409
+ return;
309410
+ }
309411
+ console.log("Daemon is not running. Start it with 'clankie start' when ready.");
309412
+ }
309298
309413
  function cmdStatus() {
309299
309414
  const status = isRunning();
309300
309415
  if (status.running) console.log(`Daemon is running (pid ${status.pid}).`);
@@ -309418,6 +309533,10 @@ async function main() {
309418
309533
  case "restart":
309419
309534
  await cmdRestart();
309420
309535
  break;
309536
+ case "update":
309537
+ case "self-update":
309538
+ await cmdUpdate();
309539
+ break;
309421
309540
  case "status":
309422
309541
  cmdStatus();
309423
309542
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clankie",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "A minimal personal AI assistant built on pi's SDK",
5
5
  "type": "module",
6
6
  "bin": {
@@ -22,7 +22,7 @@
22
22
  "check:fix": "biome check --fix .",
23
23
  "format": "biome format --write .",
24
24
  "typecheck": "tsgo --noEmit",
25
- "typecheck:all": "tsgo --noEmit && cd web-ui && npx tsgo --noEmit && cd ../extensions/clankie-memory && npx tsgo --noEmit"
25
+ "typecheck:all": "tsgo --noEmit && cd web-ui && npx tsgo --noEmit && cd ../extensions/clankie-memory && npx tsgo --noEmit && cd ../clankie-json-ui-render && npx tsgo --noEmit"
26
26
  },
27
27
  "engines": {
28
28
  "node": ">=18.0.0"
@@ -1,2 +1,2 @@
1
- <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>clankie — Personal AI Assistant</title><link rel="modulepreload" href="/assets/main-D1-MPeAM.js"/><link rel="modulepreload" href="/assets/index-DDPzWyca.js"/><link rel="icon" type="image/svg+xml" href="/favicon.svg"/><link rel="stylesheet" href="/assets/styles-C4OT29Wk.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)] border-r border-border/20"><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="p-2 flex flex-col gap-3 px-4 py-4"><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 [&amp;&gt;span:last-child]:truncate [&amp;_svg]:size-4 [&amp;_svg]:shrink-0 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground text-sm group-data-[collapsible=icon]:p-0! h-10 active" href="/" data-status="active" aria-current="page"><div class="flex items-center gap-3"><div class="flex items-center justify-center w-8 h-8 rounded-xl bg-primary/15 border border-primary/20"><span class="text-sm font-mono font-bold text-primary">c/</span></div><span class="text-lg font-mono font-semibold tracking-tight text-sidebar-foreground">clankie</span></div></a></li></ul><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_spb6_" 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 p-2 text-left 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 [&amp;&gt;span:last-child]:truncate [&amp;_svg]:size-4 [&amp;_svg]:shrink-0 h-10 text-sm font-medium bg-primary text-primary-foreground hover:bg-primary/90 hover:text-primary-foreground active:bg-primary/90 active:text-primary-foreground transition-all rounded-xl"><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 h-4 w-4 mr-1" aria-hidden="true"><circle cx="12" cy="12" r="10"></circle><path d="M8 12h8"></path><path d="M12 8v8"></path></svg><span>New Chat</span></button></li></ul></div><div data-slot="sidebar-content" data-sidebar="content" class="no-scrollbar flex min-h-0 flex-1 flex-col overflow-auto group-data-[collapsible=icon]:overflow-hidden gap-2 px-2 py-2"><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 py-2"><div data-slot="sidebar-group-label" data-sidebar="group-label" class="ring-sidebar-ring h-8 rounded-md transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&amp;&gt;svg]:size-4 flex shrink-0 items-center outline-hidden [&amp;&gt;svg]:shrink-0 text-[11px] font-medium uppercase tracking-wider text-muted-foreground/40 px-3 py-2">Recent</div><ul data-slot="sidebar-menu" data-sidebar="menu" class="flex w-full min-w-0 flex-col gap-1 px-1"><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 [&amp;&gt;span:last-child]:truncate [&amp;_svg]:size-4 [&amp;_svg]:shrink-0 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground text-sm h-12 opacity-40" disabled=""><span class="text-sm text-sidebar-foreground/40">No sessions yet</span></button></li></ul></div></div><div data-slot="sidebar-footer" data-sidebar="footer" class="gap-2 p-2 flex flex-col px-2 py-2"><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="dropdown-menu-trigger" 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 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 [&amp;&gt;span:last-child]:truncate [&amp;_svg]:size-4 [&amp;_svg]:shrink-0 hover:bg-sidebar-accent h-10 text-sm text-sidebar-foreground/70 hover:text-sidebar-foreground rounded-xl" tabindex="0" aria-haspopup="menu" id="base-ui-_R_7pb6_"><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 h-4 w-4" 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></button></li></ul></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 flex w-full flex-1 flex-col relative"><div class="absolute left-4 top-3.5 z-50 md:hidden"><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 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&amp;_svg]:pointer-events-none shrink-0 [&amp;_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></div><!--$--><!--$--><!--/$--><script></script><!--/$--></main></div><section aria-label="Notifications alt+T" tabindex="-1" aria-live="polite" aria-relevant="additions text" aria-atomic="false"></section><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-D1-MPeAM.js"],assets:$R[5]=[$R[6]={tag:"script",attrs:$R[7]={type:"module",async:!0},children:"import(\"/assets/main-D1-MPeAM.js\")"}]}}},matches:$R[8]=[$R[9]={i:"__root__",u:1772739330754,s:"success",ssr:!0}],lastMatchId:"__root__"})($R["tsr"]);$_TSR.e();document.currentScript.remove()</script><script type="module" async="">import("/assets/main-D1-MPeAM.js")</script></body></html>
1
+ <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>clankie — Personal AI Assistant</title><link rel="modulepreload" href="/assets/main-CP6prmzV.js"/><link rel="modulepreload" href="/assets/index-TBNB5eLy.js"/><link rel="icon" type="image/svg+xml" href="/favicon.svg"/><link rel="stylesheet" href="/assets/styles-KEhqa3CU.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)] border-r border-border/20"><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="p-2 flex flex-col gap-3 px-4 py-4"><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="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 [&amp;&gt;span:last-child]:truncate [&amp;_svg]:size-4 [&amp;_svg]:shrink-0 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground text-sm group-data-[collapsible=icon]:p-0! h-10"><div class="flex items-center gap-3"><div class="flex items-center justify-center w-8 h-8 rounded-xl bg-primary/15 border border-primary/20"><span class="text-sm font-mono font-bold text-primary">c/</span></div><span class="text-lg font-mono font-semibold tracking-tight text-sidebar-foreground">clankie</span></div></button></li></ul><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_1phb6_" 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 p-2 text-left 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 [&amp;&gt;span:last-child]:truncate [&amp;_svg]:size-4 [&amp;_svg]:shrink-0 h-10 text-sm font-medium bg-primary text-primary-foreground hover:bg-primary/90 hover:text-primary-foreground active:bg-primary/90 active:text-primary-foreground transition-all rounded-xl"><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 h-4 w-4 mr-1" aria-hidden="true"><circle cx="12" cy="12" r="10"></circle><path d="M8 12h8"></path><path d="M12 8v8"></path></svg><span>New Chat</span></button></li></ul></div><div data-slot="sidebar-content" data-sidebar="content" class="no-scrollbar flex min-h-0 flex-1 flex-col overflow-auto group-data-[collapsible=icon]:overflow-hidden gap-2 px-2 py-2"><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 py-2"><div data-slot="sidebar-group-label" data-sidebar="group-label" class="ring-sidebar-ring h-8 rounded-md transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&amp;&gt;svg]:size-4 flex shrink-0 items-center outline-hidden [&amp;&gt;svg]:shrink-0 text-[11px] font-medium uppercase tracking-wider text-muted-foreground/40 px-3 py-2">Recent</div><ul data-slot="sidebar-menu" data-sidebar="menu" class="flex w-full min-w-0 flex-col gap-1 px-1"><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 [&amp;&gt;span:last-child]:truncate [&amp;_svg]:size-4 [&amp;_svg]:shrink-0 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground text-sm h-12 opacity-40" disabled=""><span class="text-sm text-sidebar-foreground/40">No sessions yet</span></button></li></ul></div></div><div data-slot="sidebar-footer" data-sidebar="footer" class="gap-2 p-2 flex flex-col px-2 py-2"><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="dropdown-menu-trigger" 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 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 [&amp;&gt;span:last-child]:truncate [&amp;_svg]:size-4 [&amp;_svg]:shrink-0 hover:bg-sidebar-accent h-10 text-sm text-sidebar-foreground/70 hover:text-sidebar-foreground rounded-xl" tabindex="0" aria-haspopup="menu" id="base-ui-_R_fhb6_"><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 h-4 w-4" 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></button></li></ul></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 flex w-full flex-1 flex-col relative min-h-0"><header class="topbar-glass sticky top-0 z-40 flex h-14 shrink-0 items-center border-b px-4 md:hidden"><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 [&amp;_svg:not([class*=&#x27;size-&#x27;])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&amp;_svg]:pointer-events-none shrink-0 [&amp;_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><div class="min-h-0 flex-1"><!--$--><!--$--><!--/$--><script></script><!--/$--></div></main></div><section aria-label="Notifications alt+T" tabindex="-1" aria-live="polite" aria-relevant="additions text" aria-atomic="false"></section><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-CP6prmzV.js"],assets:$R[5]=[$R[6]={tag:"script",attrs:$R[7]={type:"module",async:!0},children:"import(\"/assets/main-CP6prmzV.js\")"}]}}},matches:$R[8]=[$R[9]={i:"__root__",u:1772806123370,s:"success",ssr:!0}],lastMatchId:"__root__"})($R["tsr"]);$_TSR.e();document.currentScript.remove()</script><script type="module" async="">import("/assets/main-CP6prmzV.js")</script></body></html>
@@ -1 +1 @@
1
- import{i as b,z as R,A as K,D as O,E,r as u,j as e,H as T,J as B,w as p,M as V,N as U,B as x,O as $,Q as q,R as H,a as A,U as S,V as Y,m as j,o as y,I,c as W,W as X,X as w,s as J,Y as Q,C as D,g as P,h as F,n as Z,e as L,K as G,Z as ee,_ as te}from"./main-D1-MPeAM.js";import{F as k,a as z}from"./field-BbqZG4RJ.js";import{C as M}from"./circle-x-DXPT4pz6.js";import{B as se}from"./badge-CFXQDPlY.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"}]],ne=b("circle-check-big",ae);const re=[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]],ie=b("external-link",re);const oe=[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}]],_=b("shield",oe);function le(t){const{children:a,open:s,defaultOpen:l=!1,onOpenChange:r,onOpenChangeComplete:i,actionsRef:m,handle:f,triggerId:g,defaultTriggerId:h=null}=t,v=R(),N=!!v,c=K(()=>f?.store??new O({open:l,openProp:s,activeTriggerId:h,triggerIdProp:g,modal:!0,disablePointerDismissal:!0,nested:N,role:"alertdialog"})).current;c.useControlledProp("openProp",s),c.useControlledProp("triggerIdProp",g),c.useSyncedValue("nested",N),c.useContextCallback("onOpenChange",r),c.useContextCallback("onOpenChangeComplete",i);const C=c.useState("payload");E({store:c,actionsRef:m,parentContext:v?.store.context});const n=u.useMemo(()=>({store:c}),[c]);return e.jsx(T.Provider,{value:n,children:typeof a=="function"?a({payload:C}):a})}function ce({...t}){return e.jsx(le,{"data-slot":"alert-dialog",...t})}function de({...t}){return e.jsx(q,{"data-slot":"alert-dialog-portal",...t})}function ue({className:t,...a}){return e.jsx(H,{"data-slot":"alert-dialog-overlay",className:p("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50",t),...a})}function me({className:t,size:a="default",...s}){return e.jsxs(de,{children:[e.jsx(ue,{}),e.jsx(B,{"data-slot":"alert-dialog-content","data-size":a,className:p("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 bg-background ring-foreground/10 gap-4 rounded-xl p-4 ring-1 duration-100 data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 outline-none",t),...s})]})}function xe({className:t,...a}){return e.jsx("div",{"data-slot":"alert-dialog-header",className:p("grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]",t),...a})}function ge({className:t,...a}){return e.jsx("div",{"data-slot":"alert-dialog-footer",className:p("bg-muted/50 -mx-4 -mb-4 rounded-b-xl border-t p-4 flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",t),...a})}function he({className:t,...a}){return e.jsx(V,{"data-slot":"alert-dialog-title",className:p("text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2",t),...a})}function pe({className:t,...a}){return e.jsx(U,{"data-slot":"alert-dialog-description",className:p("text-muted-foreground *:[a]:hover:text-foreground text-sm text-balance md:text-pretty *:[a]:underline *:[a]:underline-offset-3",t),...a})}function fe({className:t,...a}){return e.jsx(x,{"data-slot":"alert-dialog-action",className:p(t),...a})}function je({className:t,variant:a="outline",size:s="default",...l}){return e.jsx($,{"data-slot":"alert-dialog-cancel",className:p(t),render:e.jsx(x,{variant:a,size:s}),...l})}function ye({open:t,onOpenChange:a}){const{loginFlow:s}=A(S,i=>({loginFlow:i.loginFlow}));if(u.useEffect(()=>{!t&&s&&Y()},[t,s]),u.useEffect(()=>{if(t&&s?.status==="complete"&&s.success===!0){const i=setTimeout(()=>{a(!1)},1500);return()=>clearTimeout(i)}},[t,s,a]),!s)return null;const l=()=>{s.loginFlowId&&s.status!=="complete"&&s.status!=="error"&&j.getClient()?.authLoginCancel(s.loginFlowId),a(!1)},r=()=>{a(!1)};return e.jsx(ce,{open:t,onOpenChange:a,children:e.jsxs(me,{children:[e.jsxs(xe,{children:[e.jsx(he,{children:s.status==="complete"&&s.success?"Login Successful":s.status==="error"?"Login Failed":`Sign in to ${s.providerId}`}),e.jsx(pe,{children:e.jsx(ve,{flow:s})})]}),e.jsx(ge,{children:s.status==="complete"||s.status==="error"?e.jsx(fe,{onClick:r,children:"Close"}):e.jsx(je,{onClick:l,children:"Cancel"})})]})})}function ve({flow:t}){const a=j.getClient(),s=u.useRef(null),l=i=>{t.loginFlowId&&a&&a.authLoginInput(t.loginFlowId,i)},r=i=>{t.loginFlowId&&a&&a.authLoginInput(t.loginFlowId,i)};return u.useEffect(()=>{t.status==="waiting_url"&&t.url&&s.current!==t.url&&(s.current=t.url,window.open(t.url,"_blank"))},[t.status,t.url]),t.status==="idle"?e.jsxs("div",{className:"flex items-center gap-3 py-4",children:[e.jsx(y,{className:"h-5 w-5 animate-spin text-muted-foreground"}),e.jsx("span",{className:"text-sm",children:"Starting login..."})]}):t.status==="waiting_url"&&t.url?e.jsxs("div",{className:"space-y-4 py-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(y,{className:"h-5 w-5 animate-spin text-muted-foreground"}),e.jsx("span",{className:"text-sm",children:"Complete the authentication in your browser..."})]}),t.instructions&&e.jsx("p",{className:"text-xs text-muted-foreground rounded-md bg-muted p-2",children:t.instructions}),e.jsxs(x,{onClick:()=>window.open(t.url,"_blank"),className:"w-full",variant:"outline",size:"sm",children:[e.jsx(ie,{className:"mr-2 h-4 w-4"}),"Open in Browser"]}),t.showManualInput&&e.jsx(Ne,{onSubmit:l}),t.progressMessage&&e.jsxs("div",{className:"flex items-center gap-2 text-xs text-muted-foreground",children:[e.jsx(y,{className:"h-3 w-3 animate-spin"}),e.jsx("span",{children:t.progressMessage})]})]}):t.status==="waiting_input"&&t.promptMessage?e.jsx("div",{className:"py-4",children:e.jsx(Ce,{message:t.promptMessage,placeholder:t.promptPlaceholder,onSubmit:r})}):t.status==="in_progress"?e.jsxs("div",{className:"flex items-center gap-3 py-4",children:[e.jsx(y,{className:"h-5 w-5 animate-spin text-muted-foreground"}),e.jsx("span",{className:"text-sm",children:t.progressMessage||"Completing authentication..."})]}):t.status==="complete"&&t.success?e.jsxs("div",{className:"flex items-center gap-3 py-4 text-green-600",children:[e.jsx(ne,{className:"h-5 w-5"}),e.jsxs("span",{className:"text-sm",children:["Successfully authenticated with ",t.providerId]})]}):t.status==="error"||t.status==="complete"&&!t.success?e.jsxs("div",{className:"space-y-2 py-4",children:[e.jsxs("div",{className:"flex items-center gap-3 text-destructive",children:[e.jsx(M,{className:"h-5 w-5"}),e.jsx("span",{className:"text-sm font-medium",children:"Authentication failed"})]}),t.error&&e.jsx("p",{className:"text-xs text-muted-foreground rounded-md bg-muted p-2",children:t.error})]}):null}function Ne({onSubmit:t}){const a=s=>{s.preventDefault();const r=new FormData(s.currentTarget).get("code");r?.trim()&&t(r.trim())};return e.jsx("form",{onSubmit:a,className:"space-y-2",children:e.jsxs(k,{children:[e.jsx(z,{htmlFor:"manual-code",children:"Or paste the authorization code/URL here:"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(I,{id:"manual-code",name:"code",type:"text",placeholder:"Paste code or redirect URL",className:"flex-1"}),e.jsx(x,{type:"submit",size:"sm",children:"Submit"})]})]})})}function Ce({message:t,placeholder:a,onSubmit:s}){const l=r=>{r.preventDefault();const m=new FormData(r.currentTarget).get("prompt-value");m?.trim()&&s(m.trim())};return e.jsxs("form",{onSubmit:l,className:"space-y-3",children:[e.jsx("p",{className:"text-sm",children:t}),e.jsx(k,{children:e.jsxs("div",{className:"flex gap-2",children:[e.jsx(I,{id:"prompt-value",name:"prompt-value",type:"text",placeholder:a||"Enter value",className:"flex-1",autoFocus:!0}),e.jsx(x,{type:"submit",size:"sm",children:"Submit"})]})})]})}function Pe(){const{status:t}=A(W,s=>({status:s.status}));return t==="connected"?e.jsx(be,{}):e.jsx("div",{className:"h-full flex items-center justify-center chat-background",children:e.jsxs("div",{className:"text-center space-y-4 max-w-md p-8",children:[e.jsx("div",{className:"inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-destructive/10 border border-destructive/20 mb-2",children:e.jsx(_,{className:"h-8 w-8 text-destructive"})}),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:"Connect to clankie to manage AI provider authentication"})]})]})})}function be(){const{providers:t,isLoadingProviders:a,loginFlow:s}=A(S,n=>({providers:n.providers,isLoadingProviders:n.isLoadingProviders,loginFlow:n.loginFlow})),[l,r]=u.useState(!1),[i,m]=u.useState(null),[f,g]=u.useState(""),h=u.useCallback(async()=>{const n=j.getClient();if(n){X(!0);try{const{providers:o}=await n.getAuthProviders();w(o)}catch(o){console.error("Failed to load auth providers:",o),w([])}}},[]);u.useEffect(()=>{h()},[h]),u.useEffect(()=>{if(s?.status==="complete"&&s.success===!0){h();const{activeSessionId:n}=J.state;if(n){const o=j.getClient();o&&o.getAvailableModels(n).then(({models:d})=>{Q(d),console.log("[settings/auth] Refreshed available models after OAuth login")}).catch(d=>{console.error("[settings/auth] Failed to refresh available models:",d)})}}},[s?.status,s?.success,h]);const v=async n=>{const o=j.getClient();if(o)try{const{loginFlowId:d}=await o.authLogin(n);te(d,n),r(!0)}catch(d){console.error("Failed to start login:",d)}},N=n=>{m(n),g("")},c=async n=>{const o=j.getClient();if(!(!o||!f.trim()))try{await o.authSetApiKey(n,f.trim()),m(null),g(""),await h()}catch(d){console.error("Failed to save API key:",d)}},C=async n=>{const o=j.getClient();if(o)try{await o.authLogout(n),await h()}catch(d){console.error("Failed to logout:",d)}};return e.jsxs("div",{className:"h-full overflow-y-auto chat-background",children:[e.jsxs("div",{className:"container max-w-2xl py-8 px-4",children:[e.jsxs(D,{className:"card-depth",children:[e.jsxs(P,{children:[e.jsx(F,{children:"AI Provider Authentication"}),e.jsx(Z,{children:"Configure authentication for AI providers (OpenAI, Anthropic, etc.)"})]}),e.jsx(L,{children:a?e.jsx("div",{className:"flex items-center justify-center py-8",children:e.jsx(y,{className:"h-6 w-6 animate-spin text-muted-foreground"})}):t.length===0?e.jsx("p",{className:"text-sm text-muted-foreground py-4",children:"No providers available. Make sure clankie is configured with at least one AI provider."}):e.jsx("div",{className:"space-y-3",children:t.map(n=>e.jsx(Ae,{provider:n,isEditing:i===n.id,apiKeyValue:f,onApiKeyChange:g,onLogin:()=>n.type==="oauth"?v(n.id):N(n.id),onSaveApiKey:()=>c(n.id),onCancelApiKey:()=>m(null),onLogout:()=>C(n.id)},n.id))})})]}),e.jsxs(D,{className:"mt-4 card-depth",children:[e.jsx(P,{children:e.jsx(F,{children:"About Provider Authentication"})}),e.jsxs(L,{className:"space-y-3 text-sm text-muted-foreground",children:[e.jsx("p",{children:"AI providers require authentication to access their APIs. You can authenticate using:"}),e.jsxs("ul",{className:"list-disc list-inside space-y-1",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"OAuth"})," - Browser-based authentication flow for supported providers"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"API Key"})," - Direct API key entry for providers that support it"]})]}),e.jsx("p",{className:"text-xs",children:"Your credentials are stored securely by clankie and are never shared with the web UI."})]})]})]}),e.jsx(ye,{open:l,onOpenChange:r})]})}function Ae({provider:t,isEditing:a,apiKeyValue:s,onApiKeyChange:l,onLogin:r,onSaveApiKey:i,onCancelApiKey:m,onLogout:f}){return e.jsx("div",{className:"rounded-lg border p-4",children:e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx("h4",{className:"font-medium",children:t.name}),e.jsx(se,{variant:t.type==="oauth"?"default":"secondary",className:"text-xs",children:t.type==="oauth"?e.jsxs(e.Fragment,{children:[e.jsx(_,{className:"h-3 w-3 mr-1"}),"OAuth"]}):e.jsxs(e.Fragment,{children:[e.jsx(G,{className:"h-3 w-3 mr-1"}),"API Key"]})}),t.hasAuth?e.jsx(ee,{className:"h-4 w-4 text-green-600"}):e.jsx(M,{className:"h-4 w-4 text-muted-foreground"})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:t.hasAuth?"Authenticated":"Not configured"}),a&&t.type==="apikey"&&e.jsxs("div",{className:"mt-3 space-y-2",children:[e.jsxs(k,{children:[e.jsx(z,{htmlFor:`api-key-${t.id}`,children:"API Key"}),e.jsx(I,{id:`api-key-${t.id}`,type:"password",placeholder:"Enter API key",value:s,onChange:g=>l(g.target.value),autoFocus:!0})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(x,{size:"sm",onClick:i,disabled:!s.trim(),children:"Save"}),e.jsx(x,{size:"sm",variant:"outline",onClick:m,children:"Cancel"})]})]})]}),!a&&e.jsx("div",{className:"flex gap-2",children:t.hasAuth?e.jsx(x,{size:"sm",variant:"outline",onClick:f,children:"Logout"}):e.jsx(x,{size:"sm",onClick:r,children:"Login"})})]})})}export{Pe as component};
1
+ import{i as b,A as R,D as K,E as O,H as E,r as u,j as e,J as T,M as B,x as p,N as V,O as $,B as x,Q as U,R as q,U as H,a as A,V as S,W as Y,m as j,o as y,I,c as W,X,Y as D,s as J,Z as Q,C as w,g as P,h as F,n as Z,e as L,K as G,_ as ee,$ as te}from"./main-CP6prmzV.js";import{F as k,a as z}from"./field-DfBj0pPw.js";import{C as M}from"./circle-x-B1Pwi07a.js";import{B as se}from"./badge-3e57zy_2.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"}]],ne=b("circle-check-big",ae);const re=[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]],ie=b("external-link",re);const oe=[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}]],_=b("shield",oe);function le(t){const{children:a,open:s,defaultOpen:l=!1,onOpenChange:r,onOpenChangeComplete:i,actionsRef:m,handle:f,triggerId:g,defaultTriggerId:h=null}=t,v=R(),N=!!v,c=K(()=>f?.store??new O({open:l,openProp:s,activeTriggerId:h,triggerIdProp:g,modal:!0,disablePointerDismissal:!0,nested:N,role:"alertdialog"})).current;c.useControlledProp("openProp",s),c.useControlledProp("triggerIdProp",g),c.useSyncedValue("nested",N),c.useContextCallback("onOpenChange",r),c.useContextCallback("onOpenChangeComplete",i);const C=c.useState("payload");E({store:c,actionsRef:m,parentContext:v?.store.context});const n=u.useMemo(()=>({store:c}),[c]);return e.jsx(T.Provider,{value:n,children:typeof a=="function"?a({payload:C}):a})}function ce({...t}){return e.jsx(le,{"data-slot":"alert-dialog",...t})}function de({...t}){return e.jsx(q,{"data-slot":"alert-dialog-portal",...t})}function ue({className:t,...a}){return e.jsx(H,{"data-slot":"alert-dialog-overlay",className:p("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50",t),...a})}function me({className:t,size:a="default",...s}){return e.jsxs(de,{children:[e.jsx(ue,{}),e.jsx(B,{"data-slot":"alert-dialog-content","data-size":a,className:p("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 bg-background ring-foreground/10 gap-4 rounded-xl p-4 ring-1 duration-100 data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 outline-none",t),...s})]})}function xe({className:t,...a}){return e.jsx("div",{"data-slot":"alert-dialog-header",className:p("grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]",t),...a})}function ge({className:t,...a}){return e.jsx("div",{"data-slot":"alert-dialog-footer",className:p("bg-muted/50 -mx-4 -mb-4 rounded-b-xl border-t p-4 flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",t),...a})}function he({className:t,...a}){return e.jsx(V,{"data-slot":"alert-dialog-title",className:p("text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2",t),...a})}function pe({className:t,...a}){return e.jsx($,{"data-slot":"alert-dialog-description",className:p("text-muted-foreground *:[a]:hover:text-foreground text-sm text-balance md:text-pretty *:[a]:underline *:[a]:underline-offset-3",t),...a})}function fe({className:t,...a}){return e.jsx(x,{"data-slot":"alert-dialog-action",className:p(t),...a})}function je({className:t,variant:a="outline",size:s="default",...l}){return e.jsx(U,{"data-slot":"alert-dialog-cancel",className:p(t),render:e.jsx(x,{variant:a,size:s}),...l})}function ye({open:t,onOpenChange:a}){const{loginFlow:s}=A(S,i=>({loginFlow:i.loginFlow}));if(u.useEffect(()=>{!t&&s&&Y()},[t,s]),u.useEffect(()=>{if(t&&s?.status==="complete"&&s.success===!0){const i=setTimeout(()=>{a(!1)},1500);return()=>clearTimeout(i)}},[t,s,a]),!s)return null;const l=()=>{s.loginFlowId&&s.status!=="complete"&&s.status!=="error"&&j.getClient()?.authLoginCancel(s.loginFlowId),a(!1)},r=()=>{a(!1)};return e.jsx(ce,{open:t,onOpenChange:a,children:e.jsxs(me,{children:[e.jsxs(xe,{children:[e.jsx(he,{children:s.status==="complete"&&s.success?"Login Successful":s.status==="error"?"Login Failed":`Sign in to ${s.providerId}`}),e.jsx(pe,{children:e.jsx(ve,{flow:s})})]}),e.jsx(ge,{children:s.status==="complete"||s.status==="error"?e.jsx(fe,{onClick:r,children:"Close"}):e.jsx(je,{onClick:l,children:"Cancel"})})]})})}function ve({flow:t}){const a=j.getClient(),s=u.useRef(null),l=i=>{t.loginFlowId&&a&&a.authLoginInput(t.loginFlowId,i)},r=i=>{t.loginFlowId&&a&&a.authLoginInput(t.loginFlowId,i)};return u.useEffect(()=>{t.status==="waiting_url"&&t.url&&s.current!==t.url&&(s.current=t.url,window.open(t.url,"_blank"))},[t.status,t.url]),t.status==="idle"?e.jsxs("div",{className:"flex items-center gap-3 py-4",children:[e.jsx(y,{className:"h-5 w-5 animate-spin text-muted-foreground"}),e.jsx("span",{className:"text-sm",children:"Starting login..."})]}):t.status==="waiting_url"&&t.url?e.jsxs("div",{className:"space-y-4 py-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(y,{className:"h-5 w-5 animate-spin text-muted-foreground"}),e.jsx("span",{className:"text-sm",children:"Complete the authentication in your browser..."})]}),t.instructions&&e.jsx("p",{className:"text-xs text-muted-foreground rounded-md bg-muted p-2",children:t.instructions}),e.jsxs(x,{onClick:()=>window.open(t.url,"_blank"),className:"w-full",variant:"outline",size:"sm",children:[e.jsx(ie,{className:"mr-2 h-4 w-4"}),"Open in Browser"]}),t.showManualInput&&e.jsx(Ne,{onSubmit:l}),t.progressMessage&&e.jsxs("div",{className:"flex items-center gap-2 text-xs text-muted-foreground",children:[e.jsx(y,{className:"h-3 w-3 animate-spin"}),e.jsx("span",{children:t.progressMessage})]})]}):t.status==="waiting_input"&&t.promptMessage?e.jsx("div",{className:"py-4",children:e.jsx(Ce,{message:t.promptMessage,placeholder:t.promptPlaceholder,onSubmit:r})}):t.status==="in_progress"?e.jsxs("div",{className:"flex items-center gap-3 py-4",children:[e.jsx(y,{className:"h-5 w-5 animate-spin text-muted-foreground"}),e.jsx("span",{className:"text-sm",children:t.progressMessage||"Completing authentication..."})]}):t.status==="complete"&&t.success?e.jsxs("div",{className:"flex items-center gap-3 py-4 text-green-600",children:[e.jsx(ne,{className:"h-5 w-5"}),e.jsxs("span",{className:"text-sm",children:["Successfully authenticated with ",t.providerId]})]}):t.status==="error"||t.status==="complete"&&!t.success?e.jsxs("div",{className:"space-y-2 py-4",children:[e.jsxs("div",{className:"flex items-center gap-3 text-destructive",children:[e.jsx(M,{className:"h-5 w-5"}),e.jsx("span",{className:"text-sm font-medium",children:"Authentication failed"})]}),t.error&&e.jsx("p",{className:"text-xs text-muted-foreground rounded-md bg-muted p-2",children:t.error})]}):null}function Ne({onSubmit:t}){const a=s=>{s.preventDefault();const r=new FormData(s.currentTarget).get("code");r?.trim()&&t(r.trim())};return e.jsx("form",{onSubmit:a,className:"space-y-2",children:e.jsxs(k,{children:[e.jsx(z,{htmlFor:"manual-code",children:"Or paste the authorization code/URL here:"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(I,{id:"manual-code",name:"code",type:"text",placeholder:"Paste code or redirect URL",className:"flex-1"}),e.jsx(x,{type:"submit",size:"sm",children:"Submit"})]})]})})}function Ce({message:t,placeholder:a,onSubmit:s}){const l=r=>{r.preventDefault();const m=new FormData(r.currentTarget).get("prompt-value");m?.trim()&&s(m.trim())};return e.jsxs("form",{onSubmit:l,className:"space-y-3",children:[e.jsx("p",{className:"text-sm",children:t}),e.jsx(k,{children:e.jsxs("div",{className:"flex gap-2",children:[e.jsx(I,{id:"prompt-value",name:"prompt-value",type:"text",placeholder:a||"Enter value",className:"flex-1",autoFocus:!0}),e.jsx(x,{type:"submit",size:"sm",children:"Submit"})]})})]})}function Pe(){const{status:t}=A(W,s=>({status:s.status}));return t==="connected"?e.jsx(be,{}):e.jsx("div",{className:"h-full flex items-center justify-center chat-background",children:e.jsxs("div",{className:"text-center space-y-4 max-w-md p-8",children:[e.jsx("div",{className:"inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-destructive/10 border border-destructive/20 mb-2",children:e.jsx(_,{className:"h-8 w-8 text-destructive"})}),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:"Connect to clankie to manage AI provider authentication"})]})]})})}function be(){const{providers:t,isLoadingProviders:a,loginFlow:s}=A(S,n=>({providers:n.providers,isLoadingProviders:n.isLoadingProviders,loginFlow:n.loginFlow})),[l,r]=u.useState(!1),[i,m]=u.useState(null),[f,g]=u.useState(""),h=u.useCallback(async()=>{const n=j.getClient();if(n){X(!0);try{const{providers:o}=await n.getAuthProviders();D(o)}catch(o){console.error("Failed to load auth providers:",o),D([])}}},[]);u.useEffect(()=>{h()},[h]),u.useEffect(()=>{if(s?.status==="complete"&&s.success===!0){h();const{activeSessionId:n}=J.state;if(n){const o=j.getClient();o&&o.getAvailableModels(n).then(({models:d})=>{Q(d),console.log("[settings/auth] Refreshed available models after OAuth login")}).catch(d=>{console.error("[settings/auth] Failed to refresh available models:",d)})}}},[s?.status,s?.success,h]);const v=async n=>{const o=j.getClient();if(o)try{const{loginFlowId:d}=await o.authLogin(n);te(d,n),r(!0)}catch(d){console.error("Failed to start login:",d)}},N=n=>{m(n),g("")},c=async n=>{const o=j.getClient();if(!(!o||!f.trim()))try{await o.authSetApiKey(n,f.trim()),m(null),g(""),await h()}catch(d){console.error("Failed to save API key:",d)}},C=async n=>{const o=j.getClient();if(o)try{await o.authLogout(n),await h()}catch(d){console.error("Failed to logout:",d)}};return e.jsxs("div",{className:"h-full overflow-y-auto chat-background",children:[e.jsxs("div",{className:"container max-w-2xl py-8 px-4",children:[e.jsxs(w,{className:"card-depth",children:[e.jsxs(P,{children:[e.jsx(F,{children:"AI Provider Authentication"}),e.jsx(Z,{children:"Configure authentication for AI providers (OpenAI, Anthropic, etc.)"})]}),e.jsx(L,{children:a?e.jsx("div",{className:"flex items-center justify-center py-8",children:e.jsx(y,{className:"h-6 w-6 animate-spin text-muted-foreground"})}):t.length===0?e.jsx("p",{className:"text-sm text-muted-foreground py-4",children:"No providers available. Make sure clankie is configured with at least one AI provider."}):e.jsx("div",{className:"space-y-3",children:t.map(n=>e.jsx(Ae,{provider:n,isEditing:i===n.id,apiKeyValue:f,onApiKeyChange:g,onLogin:()=>n.type==="oauth"?v(n.id):N(n.id),onSaveApiKey:()=>c(n.id),onCancelApiKey:()=>m(null),onLogout:()=>C(n.id)},n.id))})})]}),e.jsxs(w,{className:"mt-4 card-depth",children:[e.jsx(P,{children:e.jsx(F,{children:"About Provider Authentication"})}),e.jsxs(L,{className:"space-y-3 text-sm text-muted-foreground",children:[e.jsx("p",{children:"AI providers require authentication to access their APIs. You can authenticate using:"}),e.jsxs("ul",{className:"list-disc list-inside space-y-1",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"OAuth"})," - Browser-based authentication flow for supported providers"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"API Key"})," - Direct API key entry for providers that support it"]})]}),e.jsx("p",{className:"text-xs",children:"Your credentials are stored securely by clankie and are never shared with the web UI."})]})]})]}),e.jsx(ye,{open:l,onOpenChange:r})]})}function Ae({provider:t,isEditing:a,apiKeyValue:s,onApiKeyChange:l,onLogin:r,onSaveApiKey:i,onCancelApiKey:m,onLogout:f}){return e.jsx("div",{className:"rounded-lg border p-4",children:e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx("h4",{className:"font-medium",children:t.name}),e.jsx(se,{variant:t.type==="oauth"?"default":"secondary",className:"text-xs",children:t.type==="oauth"?e.jsxs(e.Fragment,{children:[e.jsx(_,{className:"h-3 w-3 mr-1"}),"OAuth"]}):e.jsxs(e.Fragment,{children:[e.jsx(G,{className:"h-3 w-3 mr-1"}),"API Key"]})}),t.hasAuth?e.jsx(ee,{className:"h-4 w-4 text-green-600"}):e.jsx(M,{className:"h-4 w-4 text-muted-foreground"})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:t.hasAuth?"Authenticated":"Not configured"}),a&&t.type==="apikey"&&e.jsxs("div",{className:"mt-3 space-y-2",children:[e.jsxs(k,{children:[e.jsx(z,{htmlFor:`api-key-${t.id}`,children:"API Key"}),e.jsx(I,{id:`api-key-${t.id}`,type:"password",placeholder:"Enter API key",value:s,onChange:g=>l(g.target.value),autoFocus:!0})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(x,{size:"sm",onClick:i,disabled:!s.trim(),children:"Save"}),e.jsx(x,{size:"sm",variant:"outline",onClick:m,children:"Cancel"})]})]})]}),!a&&e.jsx("div",{className:"flex gap-2",children:t.hasAuth?e.jsx(x,{size:"sm",variant:"outline",onClick:f,children:"Logout"}):e.jsx(x,{size:"sm",onClick:r,children:"Login"})})]})})}export{Pe as component};
@@ -0,0 +1 @@
1
+ import{a0 as i,a1 as n,x as d,a2 as s}from"./main-CP6prmzV.js";const o=s("h-5 gap-1 rounded-4xl border border-transparent 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 justify-center w-fit 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",{variants:{variant:{default:"bg-primary text-primary-foreground [a]:hover:bg-primary/80",secondary:"bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",destructive:"bg-destructive/10 [a]:hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 text-destructive dark:bg-destructive/20",outline:"border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",ghost:"hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",link:"text-primary underline-offset-4 hover:underline"}},defaultVariants:{variant:"default"}});function g({className:r,variant:e="default",render:t,...a}){return i({defaultTagName:"span",props:n({className:d(o({variant:e}),r)},a),render:t,state:{slot:"badge",variant:e}})}export{g as B};
@@ -0,0 +1 @@
1
+ import{i as c}from"./main-CP6prmzV.js";const e=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],t=c("check",e);export{t as C};
@@ -1 +1 @@
1
- import{i as c}from"./main-D1-MPeAM.js";const e=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m15 9-6 6",key:"1uzhvr"}],["path",{d:"m9 9 6 6",key:"z0biqf"}]],i=c("circle-x",e);export{i as C};
1
+ import{i as c}from"./main-CP6prmzV.js";const e=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m15 9-6 6",key:"1uzhvr"}],["path",{d:"m9 9 6 6",key:"z0biqf"}]],i=c("circle-x",e);export{i as C};
@@ -1 +1 @@
1
- import{a as S,c as w,r,j as e,C as d,g as h,h as x,n as y,e as u,I as m,B as c,L as T,S as F,y as j,m as p}from"./main-D1-MPeAM.js";import{F as g,a as k}from"./field-BbqZG4RJ.js";function A(){const{settings:o,status:l}=S(w,t=>({settings:t.settings,status:t.status})),[a,b]=r.useState(o.url),[n,v]=r.useState(o.authToken),s=l==="connected",i=l==="connecting",C=()=>{j({url:a,authToken:n})},N=()=>{j({url:a,authToken:n}),p.connect()},f=()=>{p.disconnect()};return e.jsx("div",{className:"h-full overflow-y-auto chat-background",children:e.jsxs("div",{className:"container max-w-2xl py-8 px-4",children:[e.jsxs(d,{className:"card-depth",children:[e.jsxs(h,{children:[e.jsx(x,{children:"Connection Settings"}),e.jsx(y,{children:"Configure the WebSocket connection to your clankie instance"})]}),e.jsxs(u,{className:"space-y-4",children:[e.jsxs(g,{children:[e.jsx(k,{htmlFor:"ws-url",children:"WebSocket URL"}),e.jsx(m,{id:"ws-url",type:"text",placeholder:"ws://localhost:3100",value:a,onChange:t=>b(t.target.value),disabled:s})]}),e.jsxs(g,{children:[e.jsx(k,{htmlFor:"auth-token",children:"Auth Token"}),e.jsx(m,{id:"auth-token",type:"password",placeholder:"Enter your authentication token",value:n,onChange:t=>v(t.target.value),disabled:s}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-1",children:["Set with:"," ",e.jsx("code",{className:"rounded bg-muted px-1 py-0.5",children:'clankie config set channels.web.authToken "your-token"'})]})]}),e.jsx("div",{className:"flex gap-2 pt-2",children:s?e.jsx(c,{variant:"destructive",onClick:f,children:"Disconnect"}):e.jsxs(e.Fragment,{children:[e.jsx(c,{onClick:N,disabled:i||!n,children:i?"Connecting...":"Connect"}),e.jsx(c,{variant:"outline",onClick:C,disabled:i,children:"Save"})]})}),!n&&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:"Auth token required"}),e.jsx("p",{className:"text-xs mt-1",children:"Configure the token in clankie and enter it above to connect."})]})]})]}),e.jsxs(d,{className:"mt-4 card-depth",children:[e.jsx(h,{children:e.jsx(x,{children:"Setup Instructions"})}),e.jsxs(u,{className:"space-y-3 text-sm",children:[e.jsxs("div",{children:[e.jsx("p",{className:"font-medium",children:"1. Enable the web channel in clankie"}),e.jsxs("code",{className:"block mt-1 rounded bg-muted p-2 text-xs",children:['clankie config set channels.web.authToken "your-secret-token"',e.jsx("br",{}),"clankie config set channels.web.port 3100"]})]}),e.jsxs("div",{children:[e.jsx("p",{className:"font-medium",children:"2. Start the clankie daemon"}),e.jsx("code",{className:"block mt-1 rounded bg-muted p-2 text-xs",children:"clankie start"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"font-medium",children:"3. Enter the token above and connect"}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"The web-ui will connect to ws://localhost:3100 by default"})]})]})]}),!s&&e.jsx("div",{className:"mt-4 text-center",children:e.jsx(T,{to:"/settings",children:e.jsxs(c,{variant:"outline",children:[e.jsx(F,{className:"mr-2 h-4 w-4"}),"Back to Settings"]})})})]})})}export{A as component};
1
+ import{a as S,c as w,r,j as e,C as d,g as h,h as x,n as y,e as u,I as m,B as c,L as T,S as F,z as j,m as p}from"./main-CP6prmzV.js";import{F as g,a as k}from"./field-DfBj0pPw.js";function A(){const{settings:o,status:l}=S(w,t=>({settings:t.settings,status:t.status})),[a,b]=r.useState(o.url),[n,v]=r.useState(o.authToken),s=l==="connected",i=l==="connecting",C=()=>{j({url:a,authToken:n})},N=()=>{j({url:a,authToken:n}),p.connect()},f=()=>{p.disconnect()};return e.jsx("div",{className:"h-full overflow-y-auto chat-background",children:e.jsxs("div",{className:"container max-w-2xl py-8 px-4",children:[e.jsxs(d,{className:"card-depth",children:[e.jsxs(h,{children:[e.jsx(x,{children:"Connection Settings"}),e.jsx(y,{children:"Configure the WebSocket connection to your clankie instance"})]}),e.jsxs(u,{className:"space-y-4",children:[e.jsxs(g,{children:[e.jsx(k,{htmlFor:"ws-url",children:"WebSocket URL"}),e.jsx(m,{id:"ws-url",type:"text",placeholder:"ws://localhost:3100",value:a,onChange:t=>b(t.target.value),disabled:s})]}),e.jsxs(g,{children:[e.jsx(k,{htmlFor:"auth-token",children:"Auth Token"}),e.jsx(m,{id:"auth-token",type:"password",placeholder:"Enter your authentication token",value:n,onChange:t=>v(t.target.value),disabled:s}),e.jsxs("p",{className:"text-xs text-muted-foreground mt-1",children:["Set with:"," ",e.jsx("code",{className:"rounded bg-muted px-1 py-0.5",children:'clankie config set channels.web.authToken "your-token"'})]})]}),e.jsx("div",{className:"flex gap-2 pt-2",children:s?e.jsx(c,{variant:"destructive",onClick:f,children:"Disconnect"}):e.jsxs(e.Fragment,{children:[e.jsx(c,{onClick:N,disabled:i||!n,children:i?"Connecting...":"Connect"}),e.jsx(c,{variant:"outline",onClick:C,disabled:i,children:"Save"})]})}),!n&&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:"Auth token required"}),e.jsx("p",{className:"text-xs mt-1",children:"Configure the token in clankie and enter it above to connect."})]})]})]}),e.jsxs(d,{className:"mt-4 card-depth",children:[e.jsx(h,{children:e.jsx(x,{children:"Setup Instructions"})}),e.jsxs(u,{className:"space-y-3 text-sm",children:[e.jsxs("div",{children:[e.jsx("p",{className:"font-medium",children:"1. Enable the web channel in clankie"}),e.jsxs("code",{className:"block mt-1 rounded bg-muted p-2 text-xs",children:['clankie config set channels.web.authToken "your-secret-token"',e.jsx("br",{}),"clankie config set channels.web.port 3100"]})]}),e.jsxs("div",{children:[e.jsx("p",{className:"font-medium",children:"2. Start the clankie daemon"}),e.jsx("code",{className:"block mt-1 rounded bg-muted p-2 text-xs",children:"clankie start"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"font-medium",children:"3. Enter the token above and connect"}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"The web-ui will connect to ws://localhost:3100 by default"})]})]})]}),!s&&e.jsx("div",{className:"mt-4 text-center",children:e.jsx(T,{to:"/settings",children:e.jsxs(c,{variant:"outline",children:[e.jsx(F,{className:"mr-2 h-4 w-4"}),"Back to Settings"]})})})]})})}export{A as component};
@@ -0,0 +1 @@
1
+ import{i as a,y as i}from"./main-CP6prmzV.js";const o=[["path",{d:"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5",key:"1gvzjb"}],["path",{d:"M9 18h6",key:"x1upvd"}],["path",{d:"M10 22h4",key:"ceow96"}]],c=a("lightbulb",o),l={extensions:[],extensionErrors:[],skills:[],skillDiagnostics:[],isLoading:!1,installStatus:{isInstalling:!1,output:"",exitCode:null}},e=new i(l);function r(t){e.setState(s=>({...s,isLoading:t}))}function S(t,s){e.setState(n=>({...n,extensions:t,extensionErrors:s,isLoading:!1}))}function d(t,s){e.setState(n=>({...n,skills:t,skillDiagnostics:s,isLoading:!1}))}function g(t){e.setState(s=>({...s,installStatus:{...s.installStatus,...t}}))}function f(){e.setState(t=>({...t,installStatus:{isInstalling:!1,output:"",exitCode:null,error:void 0}}))}export{c as L,d as a,S as b,g as c,e,f as r,r as s};