skykoi 2026.3.412 → 2026.3.413

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 (57) hide show
  1. package/dist/build-info.json +3 -3
  2. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  3. package/dist/{completion-cli-C4vYv68z.js → completion-cli-CnAgvf3H.js} +1 -1
  4. package/dist/{config-guard-uL42blI1.js → config-guard-K9XgRTDS.js} +4 -4
  5. package/dist/{doctor-UXLuku1H.js → doctor-Co47_2NL.js} +1 -1
  6. package/dist/{doctor-completion-Dg19Gwxi.js → doctor-completion-BQuJ38kv.js} +1 -1
  7. package/dist/entry.js +1 -1
  8. package/dist/{gateway-cli-DQrxGX-4.js → gateway-cli-BpSWIzPr.js} +182 -6
  9. package/dist/index.js +8 -8
  10. package/dist/{onboarding-CfKnJZbi.js → onboarding-sBRViahV.js} +3 -3
  11. package/dist/plugin-sdk/index.js +12 -12
  12. package/dist/plugin-sdk/{pi-model-discovery-ClImJtLC.js → pi-model-discovery-lynj0LAO.js} +3 -3
  13. package/dist/{program-C3gh4a7L.js → program-CfMxAtmt.js} +3 -3
  14. package/dist/{register.subclis-B7OaMfn1.js → register.subclis-D0eQnEI6.js} +4 -4
  15. package/dist/{run-main-B5YZEVb1.js → run-main-DGjB32Pl.js} +9 -9
  16. package/dist/{tui-LnWEBmox.js → tui-D-n6UhuD.js} +6 -13
  17. package/dist/{tui-cli-7ccTTk2g.js → tui-cli-DdsPOyEw.js} +2 -2
  18. package/dist/{tui-shell-Cb4XwIAh.js → tui-shell-DOjzcOig.js} +3 -3
  19. package/dist/{update-cli-CtqXc39J.js → update-cli-9PXRA3S_.js} +4 -4
  20. package/extensions/bluebubbles/package.json +1 -1
  21. package/extensions/copilot-proxy/package.json +1 -1
  22. package/extensions/diagnostics-otel/package.json +1 -1
  23. package/extensions/discord/package.json +1 -1
  24. package/extensions/feishu/package.json +1 -1
  25. package/extensions/google-antigravity-auth/package.json +1 -1
  26. package/extensions/google-gemini-cli-auth/package.json +1 -1
  27. package/extensions/googlechat/package.json +1 -1
  28. package/extensions/imessage/package.json +1 -1
  29. package/extensions/line/package.json +1 -1
  30. package/extensions/llm-task/package.json +1 -1
  31. package/extensions/lobster/package.json +1 -1
  32. package/extensions/matrix/CHANGELOG.md +5 -0
  33. package/extensions/matrix/package.json +1 -1
  34. package/extensions/mattermost/package.json +1 -1
  35. package/extensions/memory-core/package.json +1 -1
  36. package/extensions/memory-lancedb/package.json +1 -1
  37. package/extensions/minimax-portal-auth/package.json +1 -1
  38. package/extensions/msteams/CHANGELOG.md +5 -0
  39. package/extensions/msteams/package.json +1 -1
  40. package/extensions/nextcloud-talk/package.json +1 -1
  41. package/extensions/nostr/CHANGELOG.md +5 -0
  42. package/extensions/nostr/package.json +1 -1
  43. package/extensions/open-prose/package.json +1 -1
  44. package/extensions/signal/package.json +1 -1
  45. package/extensions/slack/package.json +1 -1
  46. package/extensions/telegram/package.json +1 -1
  47. package/extensions/tlon/package.json +1 -1
  48. package/extensions/twitch/CHANGELOG.md +5 -0
  49. package/extensions/twitch/package.json +1 -1
  50. package/extensions/voice-call/CHANGELOG.md +5 -0
  51. package/extensions/voice-call/package.json +1 -1
  52. package/extensions/whatsapp/package.json +1 -1
  53. package/extensions/zalo/CHANGELOG.md +5 -0
  54. package/extensions/zalo/package.json +1 -1
  55. package/extensions/zalouser/CHANGELOG.md +5 -0
  56. package/extensions/zalouser/package.json +1 -1
  57. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2026.3.412",
3
- "commit": "3c1f4303085287e073eb5100e7a43b764ea847c4",
4
- "builtAt": "2026-07-07T18:18:00.734Z"
2
+ "version": "2026.3.413",
3
+ "commit": "7aca16f5f011343d666f42ed37d08ff22210b553",
4
+ "builtAt": "2026-07-07T18:24:40.401Z"
5
5
  }
@@ -1 +1 @@
1
- c4ac6357b6e3d2300df1b9f87ba9f1bf415d4bd2fb0d2121a332f64959cb07de
1
+ 268a6b9221634e9da4445bdfa72f69105ffb6d1c02dcd4a93185dbc8161b172f
@@ -1,6 +1,6 @@
1
1
  import { r as __exportAll } from "./chunk-D_gEzPfs.js";
2
2
  import { g as resolveStateDir } from "./paths-VdmjGGyc.js";
3
- import { n as registerSubCliByName, t as getSubCliEntries } from "./register.subclis-B7OaMfn1.js";
3
+ import { n as registerSubCliByName, t as getSubCliEntries } from "./register.subclis-D0eQnEI6.js";
4
4
  import path from "node:path";
5
5
  import os from "node:os";
6
6
  import fs from "node:fs/promises";
@@ -29,7 +29,7 @@ import { t as resolveChannelDefaultAccountId } from "./helpers-4BXRutqw.js";
29
29
  import { n as logConfigUpdated, t as formatConfigPath } from "./logging-C3sRv-iX.js";
30
30
  import { t as WizardCancelledError } from "./prompts-BC5TXS0_.js";
31
31
  import { t as createClackPrompter } from "./clack-prompter-clPzQ9p-.js";
32
- import { a as buildKoiSummaries, c as loadKoiIdentity, f as parseIdentityMarkdown, i as applyKoiConfig, l as pruneKoiConfig, n as statusCommand, o as findKoiEntryIndex, s as listKoiEntries, t as runOnboardingWizard, u as identityHasValues } from "./onboarding-CfKnJZbi.js";
32
+ import { a as buildKoiSummaries, c as loadKoiIdentity, f as parseIdentityMarkdown, i as applyKoiConfig, l as pruneKoiConfig, n as statusCommand, o as findKoiEntryIndex, s as listKoiEntries, t as runOnboardingWizard, u as identityHasValues } from "./onboarding-sBRViahV.js";
33
33
  import { d as applyAuthChoice, f as applyOpenAIConfig, h as promptAuthChoiceGrouped, m as applyGoogleGeminiModelDefault, p as upsertSharedEnvVar, u as warnIfModelConfigLooksOff } from "./onboard-skills-BdvkU1bg.js";
34
34
  import { $ as setOpenrouterApiKey, C as applyMoonshotConfig, D as applyOpenrouterConfig, F as applyVercelAiGatewayConfig, J as setGeminiApiKey, K as setAnthropicApiKey, L as applyXaiConfig, N as applyVeniceConfig, Q as setOpencodeZenApiKey, V as applyZaiConfig, X as setMinimaxApiKey, Y as setKimiCodingApiKey, Z as setMoonshotApiKey, at as setXiaomiApiKey, et as setQianfanApiKey, f as applyOpencodeZenConfig, ft as buildTokenProfileId, g as applyMinimaxConfig, it as setXaiApiKey, j as applySyntheticConfig, k as applyQianfanConfig, m as applyMinimaxApiConfig, nt as setVeniceApiKey, ot as setZaiApiKey, pt as validateAnthropicSetupToken, q as setCloudflareAiGatewayConfig, rt as setVercelAiGatewayApiKey, tt as setSyntheticApiKey, v as applyAuthProfileConfig, w as applyMoonshotConfigCn, x as applyKimiCodeConfig, y as applyCloudflareAiGatewayConfig, z as applyXiaomiConfig } from "./github-copilot-auth-BEsuL6VZ.js";
35
35
  import { n as setupChannels } from "./onboard-channels-C7E-puRC.js";
@@ -37,7 +37,7 @@ import { i as healthCommand } from "./health-format-BFZbZLTC.js";
37
37
  import { t as renderTable } from "./table-DIfWcies.js";
38
38
  import { t as resolveGatewayService } from "./service-D1-PnhZe.js";
39
39
  import { r as isSystemdUserServiceAvailable } from "./systemd-DZP4s4qd.js";
40
- import { l as getVerboseFlag, o as getFlagValue, r as registerSubCliCommands, s as getPositiveIntFlagValue, u as hasFlag } from "./register.subclis-B7OaMfn1.js";
40
+ import { l as getVerboseFlag, o as getFlagValue, r as registerSubCliCommands, s as getPositiveIntFlagValue, u as hasFlag } from "./register.subclis-D0eQnEI6.js";
41
41
  import { n as callGatewayFromCli, t as addGatewayClientOptions } from "./gateway-rpc-DwTpsQgX.js";
42
42
  import { t as formatHelpExamples } from "./help-format-Bz-E4Xsi.js";
43
43
  import { t as adminUnlockCommand } from "./admin-unlock-CjZRxHxf.js";
@@ -48,7 +48,7 @@ import { i as CONFIGURE_WIZARD_SECTIONS, n as configureCommand, r as configureCo
48
48
  import { a as gatewayInstallErrorHint, i as buildGatewayInstallPlan, r as isGatewayDaemonRuntime, t as DEFAULT_GATEWAY_DAEMON_RUNTIME } from "./daemon-runtime-DIgqhoVa.js";
49
49
  import { n as ensureSystemdUserLingerNonInteractive } from "./systemd-linger-DHSd9ikR.js";
50
50
  import { t as loginCommand } from "./login-JCFx5Pzl.js";
51
- import { n as loadAndMaybeMigrateDoctorConfig, t as doctorCommand } from "./doctor-UXLuku1H.js";
51
+ import { n as loadAndMaybeMigrateDoctorConfig, t as doctorCommand } from "./doctor-Co47_2NL.js";
52
52
  import { fileURLToPath } from "node:url";
53
53
  import fs from "node:fs";
54
54
  import path from "node:path";
@@ -3107,7 +3107,7 @@ function registerLoginCommand(program) {
3107
3107
  console.log(theme.muted(` user=${result.userId} org=${result.orgId}`));
3108
3108
  }
3109
3109
  if (opts.chat !== false && result.gatewayUrl && process.stdin.isTTY && process.stdout.isTTY) {
3110
- const { runShell } = await import("./tui-shell-Cb4XwIAh.js").then((n) => n.n);
3110
+ const { runShell } = await import("./tui-shell-DOjzcOig.js").then((n) => n.n);
3111
3111
  console.log(theme.muted("\n Opening your koi chat…\n"));
3112
3112
  await runShell({
3113
3113
  url: result.gatewayUrl,
@@ -35,7 +35,7 @@ import { a as repairLaunchAgentBootstrap, i as launchAgentPlistExists, n as isLa
35
35
  import { r as isSystemdUserServiceAvailable } from "./systemd-DZP4s4qd.js";
36
36
  import { t as readLastGatewayErrorLine } from "./diagnostics-6vXdnH8k.js";
37
37
  import { t as collectChannelStatusIssues } from "./channels-status-issues-CGTJwSbx.js";
38
- import { n as doctorShellCompletion } from "./doctor-completion-Dg19Gwxi.js";
38
+ import { n as doctorShellCompletion } from "./doctor-completion-BQuJ38kv.js";
39
39
  import { n as resolveControlUiDistIndexHealth, r as resolveControlUiDistIndexPathForRoot } from "./control-ui-assets-D4o4damy.js";
40
40
  import { a as gatewayInstallErrorHint, d as renderSystemNodeWarning, i as buildGatewayInstallPlan, n as GATEWAY_DAEMON_RUNTIME_OPTIONS, p as resolveSystemNodeInfo, t as DEFAULT_GATEWAY_DAEMON_RUNTIME } from "./daemon-runtime-DIgqhoVa.js";
41
41
  import { t as ensureSystemdUserLingerInteractive } from "./systemd-linger-DHSd9ikR.js";
@@ -3,7 +3,7 @@ import { r as resolveCliName, t as formatCliCommand } from "./command-format-DOY
3
3
  import { t as VERSION } from "./version-B_FpLmDY.js";
4
4
  import { t as note } from "./note-PNq_JEQe.js";
5
5
  import { c as compareSemverStrings, s as checkUpdateStatus } from "./update-runner-DHNkj8-z.js";
6
- import { a as resolveCompletionCachePath, i as isCompletionInstalled, o as resolveShellFromEnv, r as installCompletion, s as usesSlowDynamicCompletion, t as completionCacheExists } from "./completion-cli-C4vYv68z.js";
6
+ import { a as resolveCompletionCachePath, i as isCompletionInstalled, o as resolveShellFromEnv, r as installCompletion, s as usesSlowDynamicCompletion, t as completionCacheExists } from "./completion-cli-CnAgvf3H.js";
7
7
  import path from "node:path";
8
8
  import { spawnSync } from "node:child_process";
9
9
 
package/dist/entry.js CHANGED
@@ -247,7 +247,7 @@ if (!ensureExperimentalWarningSuppressed()) {
247
247
  applyCliProfileEnv({ profile: parsed.profile });
248
248
  process$1.argv = parsed.argv;
249
249
  }
250
- import("./run-main-B5YZEVb1.js").then(({ runCli }) => runCli(process$1.argv)).catch((error) => {
250
+ import("./run-main-DGjB32Pl.js").then(({ runCli }) => runCli(process$1.argv)).catch((error) => {
251
251
  console.error("[SKYKOI] Failed to start CLI:", error instanceof Error ? error.stack ?? error.message : error);
252
252
  process$1.exitCode = 1;
253
253
  });
@@ -105,7 +105,7 @@ import { t as resolveChannelDefaultAccountId } from "./helpers-4BXRutqw.js";
105
105
  import "./logging-C3sRv-iX.js";
106
106
  import "./note-PNq_JEQe.js";
107
107
  import { t as WizardCancelledError } from "./prompts-BC5TXS0_.js";
108
- import { c as loadKoiIdentity, d as loadKoiIdentityFromWorkspace, i as applyKoiConfig, l as pruneKoiConfig, o as findKoiEntryIndex, r as getStatusSummary, s as listKoiEntries, t as runOnboardingWizard } from "./onboarding-CfKnJZbi.js";
108
+ import { c as loadKoiIdentity, d as loadKoiIdentityFromWorkspace, i as applyKoiConfig, l as pruneKoiConfig, o as findKoiEntryIndex, r as getStatusSummary, s as listKoiEntries, t as runOnboardingWizard } from "./onboarding-sBRViahV.js";
109
109
  import { n as installSkill } from "./onboard-skills-BdvkU1bg.js";
110
110
  import "./github-copilot-auth-BEsuL6VZ.js";
111
111
  import "./onboard-channels-C7E-puRC.js";
@@ -124,18 +124,18 @@ import { p as resolveGatewayStateDir } from "./systemd-DZP4s4qd.js";
124
124
  import "./diagnostics-6vXdnH8k.js";
125
125
  import "./node-service-Bb6tgGQx.js";
126
126
  import "./channels-status-issues-CGTJwSbx.js";
127
- import "./doctor-completion-Dg19Gwxi.js";
128
- import "./register.subclis-B7OaMfn1.js";
127
+ import "./doctor-completion-BQuJ38kv.js";
128
+ import "./register.subclis-D0eQnEI6.js";
129
129
  import { a as createOutboundSendDeps$1, i as resolveKoiOutboundTarget, r as resolveKoiDeliveryPlan, t as koiCommand } from "./koi-Cjk48UJ2.js";
130
130
  import { a as resolveControlUiRootSync, i as resolveControlUiRootOverrideSync, t as ensureControlUiAssetsBuilt } from "./control-ui-assets-D4o4damy.js";
131
131
  import "./daemon-runtime-DIgqhoVa.js";
132
132
  import { n as resolveWideAreaDiscoveryDomain, r as writeWideAreaGatewayZone } from "./widearea-dns-BjWuJvtM.js";
133
133
  import { n as discoverGatewayBeacons } from "./bonjour-discovery-3LKAHtHL.js";
134
134
  import "./ensure-local-gateway-Xk7ir7zS.js";
135
- import "./completion-cli-C4vYv68z.js";
135
+ import "./completion-cli-CnAgvf3H.js";
136
136
  import "./service-audit-BVZGmzLW.js";
137
137
  import { i as shouldIncludeHook, n as loadWorkspaceHookEntries, r as resolveHookConfig } from "./hooks-status-Cr0qf9U9.js";
138
- import "./tui-LnWEBmox.js";
138
+ import "./tui-D-n6UhuD.js";
139
139
  import "./canvas-state-C3YRnkNr.js";
140
140
  import { t as buildChannelAccountSnapshot } from "./status-pq91F0kp.js";
141
141
  import "./shared-tNGHWtW-.js";
@@ -18910,7 +18910,7 @@ function createHooksRequestHandler(opts) {
18910
18910
  };
18911
18911
  }
18912
18912
  function createGatewayHttpServer(opts) {
18913
- const { canvasHost, clients, controlUiEnabled, controlUiBasePath, controlUiRoot, openAiChatCompletionsEnabled, openResponsesEnabled, openResponsesConfig, handleHooksRequest, handlePluginRequest, resolvedAuth } = opts;
18913
+ const { canvasHost, clients, controlUiEnabled, controlUiBasePath, controlUiRoot, openAiChatCompletionsEnabled, openResponsesEnabled, openResponsesConfig, handleHooksRequest, handleConnectRequest, handlePluginRequest, resolvedAuth } = opts;
18914
18914
  const httpServer = opts.tlsOptions ? createServer$1(opts.tlsOptions, (req, res) => {
18915
18915
  handleRequest(req, res);
18916
18916
  }) : createServer((req, res) => {
@@ -18932,6 +18932,7 @@ function createGatewayHttpServer(opts) {
18932
18932
  }
18933
18933
  const configSnapshot = loadConfig();
18934
18934
  const trustedProxies = configSnapshot.gateway?.trustedProxies ?? [];
18935
+ if (handleConnectRequest && await handleConnectRequest(req, res)) return;
18935
18936
  if (await handleHooksRequest(req, res)) return;
18936
18937
  if (await handleFilesHttpRequest(req, res, {
18937
18938
  auth: resolvedAuth,
@@ -19092,6 +19093,177 @@ function createGatewayHooksRequestHandler(params) {
19092
19093
  });
19093
19094
  }
19094
19095
 
19096
+ //#endregion
19097
+ //#region src/gateway/connect-page.ts
19098
+ const CHANNELS = [
19099
+ {
19100
+ id: "email",
19101
+ name: "Email + Calendar",
19102
+ blurb: "Gmail / Google Workspace sign-in — mail, calendar, contacts"
19103
+ },
19104
+ {
19105
+ id: "imessage",
19106
+ name: "iMessage",
19107
+ blurb: "Your Messages app on this Mac"
19108
+ },
19109
+ {
19110
+ id: "telegram",
19111
+ name: "Telegram",
19112
+ blurb: "Bot token flow"
19113
+ },
19114
+ {
19115
+ id: "discord",
19116
+ name: "Discord",
19117
+ blurb: "Bot token flow"
19118
+ },
19119
+ {
19120
+ id: "slack",
19121
+ name: "Slack",
19122
+ blurb: "Workspace app tokens"
19123
+ },
19124
+ {
19125
+ id: "signal",
19126
+ name: "Signal",
19127
+ blurb: "Link as a companion device"
19128
+ }
19129
+ ];
19130
+ function isLoopback(req) {
19131
+ const a = req.socket.remoteAddress ?? "";
19132
+ return a === "127.0.0.1" || a === "::1" || a === "::ffff:127.0.0.1";
19133
+ }
19134
+ function json(res, code, body) {
19135
+ res.statusCode = code;
19136
+ res.setHeader("Content-Type", "application/json");
19137
+ res.end(JSON.stringify(body));
19138
+ }
19139
+ function page() {
19140
+ return `<!doctype html><html><head><meta charset="utf-8"><title>Connect your accounts — SkyKoi</title>
19141
+ <meta name="viewport" content="width=device-width,initial-scale=1">
19142
+ <style>
19143
+ :root{color-scheme:dark}
19144
+ body{margin:0;background:#0a0d15;color:#e4eaf5;font:16px/1.5 -apple-system,system-ui,sans-serif;padding:40px 20px}
19145
+ .wrap{max-width:860px;margin:0 auto}
19146
+ h1{font-size:26px;margin:0 0 6px}
19147
+ .sub{color:#8a92a6;margin:0 0 28px}
19148
+ .grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:14px}
19149
+ .card{background:#121828;border:1px solid #232c45;border-radius:14px;padding:18px}
19150
+ .card.wa{grid-column:1/-1;display:flex;gap:26px;align-items:center;flex-wrap:wrap;border-color:#2a5f46}
19151
+ .head{display:flex;justify-content:space-between;align-items:center}
19152
+ .name{font-weight:600}
19153
+ .dot{width:10px;height:10px;border-radius:50%;background:#4a5570}
19154
+ .dot.ok{background:#4ade80;box-shadow:0 0 10px #4ade8088}
19155
+ p{color:#8a92a6;font-size:13px;margin:8px 0 14px}
19156
+ button{background:#26355e;color:#e4eaf5;border:0;border-radius:9px;padding:10px 16px;font-size:14px;cursor:pointer}
19157
+ button:hover{background:#31447a}
19158
+ .qr{width:216px;height:216px;border-radius:12px;background:#fff;padding:10px;box-sizing:border-box}
19159
+ .steps{font-size:14px;color:#aeb6c8;margin:0;padding-left:18px}
19160
+ .steps li{margin:6px 0}
19161
+ .ok-big{color:#4ade80;font-weight:700;font-size:18px}
19162
+ .hint{display:block;color:#66708a;margin-top:8px;font-size:12px}
19163
+ </style></head><body><div class="wrap">
19164
+ <h1>Connect your accounts</h1>
19165
+ <p class="sub">Link everything your koi works with. WhatsApp scans right here — the rest open a guided sign-in.</p>
19166
+ <div class="card wa">
19167
+ <div>
19168
+ <div class="head"><span class="name">WhatsApp</span><span class="dot" id="dot-whatsapp"></span></div>
19169
+ <ol class="steps">
19170
+ <li>Open WhatsApp on your phone</li>
19171
+ <li>Settings → <b>Linked devices</b> → <b>Link a device</b></li>
19172
+ <li>Scan this code</li>
19173
+ </ol>
19174
+ <div id="wa-state" class="hint">generating code…</div>
19175
+ </div>
19176
+ <img class="qr" id="wa-qr" alt="WhatsApp QR" style="display:none">
19177
+ <div class="ok-big" id="wa-ok" style="display:none">✓ Linked — your koi can see WhatsApp now</div>
19178
+ </div>
19179
+ <div class="grid">${CHANNELS.map((c) => `
19180
+ <div class="card" id="card-${c.id}">
19181
+ <div class="head"><span class="name">${c.name}</span><span class="dot" id="dot-${c.id}"></span></div>
19182
+ <p>${c.blurb}</p>
19183
+ <button onclick="runFlow('${c.id}', this)">Connect ${c.name}</button>
19184
+ <small class="hint" id="hint-${c.id}"></small>
19185
+ </div>`).join("\n")}</div>
19186
+ </div>
19187
+ <script>
19188
+ async function waLoop(){
19189
+ const img=document.getElementById('wa-qr'),st=document.getElementById('wa-state'),ok=document.getElementById('wa-ok'),dot=document.getElementById('dot-whatsapp');
19190
+ try{
19191
+ const r=await fetch('/connect/api/whatsapp/start',{method:'POST'});
19192
+ const d=await r.json();
19193
+ if(d.linked){img.style.display='none';ok.style.display='block';st.textContent='';dot.classList.add('ok');return}
19194
+ if(d.qrDataUrl){img.src=d.qrDataUrl;img.style.display='block';st.textContent='waiting for your scan… (code refreshes automatically)'}
19195
+ const w=await fetch('/connect/api/whatsapp/wait',{method:'POST'});
19196
+ const wd=await w.json();
19197
+ if(wd.linked){img.style.display='none';ok.style.display='block';st.textContent='';dot.classList.add('ok');return}
19198
+ }catch(e){st.textContent='hiccup — retrying…'}
19199
+ setTimeout(waLoop,1500);
19200
+ }
19201
+ async function runFlow(id,btn){
19202
+ btn.textContent='Opening…';
19203
+ await fetch('/connect/api/run?channel='+id,{method:'POST'});
19204
+ document.getElementById('hint-'+id).textContent='A Terminal window opened with the '+id+' sign-in — finish there, then come back.';
19205
+ setTimeout(()=>{btn.textContent='Connect'},4000);
19206
+ }
19207
+ waLoop();
19208
+ <\/script></body></html>`;
19209
+ }
19210
+ function createConnectPageHandler(opts) {
19211
+ return async (req, res) => {
19212
+ const url = new URL(req.url ?? "/", `http://${opts.bindHost}:${opts.port}`);
19213
+ if (url.pathname !== "/connect" && !url.pathname.startsWith("/connect/")) return false;
19214
+ if (!isLoopback(req)) {
19215
+ res.statusCode = 403;
19216
+ res.end("connect page is local-only");
19217
+ return true;
19218
+ }
19219
+ try {
19220
+ if (url.pathname === "/connect") {
19221
+ res.statusCode = 200;
19222
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
19223
+ res.end(page());
19224
+ return true;
19225
+ }
19226
+ if (url.pathname === "/connect/api/whatsapp/start" && req.method === "POST") {
19227
+ const { startWebLoginWithQr } = await import("./login-qr-DAZi8Nkf.js").then((n) => n.t);
19228
+ const result = await startWebLoginWithQr({ timeoutMs: 2e4 });
19229
+ json(res, 200, {
19230
+ linked: !result.qrDataUrl && /already|linked|connected/i.test(result.message ?? ""),
19231
+ qrDataUrl: result.qrDataUrl ?? null
19232
+ });
19233
+ return true;
19234
+ }
19235
+ if (url.pathname === "/connect/api/whatsapp/wait" && req.method === "POST") {
19236
+ const { waitForWebLogin } = await import("./login-qr-DAZi8Nkf.js").then((n) => n.t);
19237
+ json(res, 200, { linked: (await waitForWebLogin({ timeoutMs: 55e3 })).connected === true });
19238
+ return true;
19239
+ }
19240
+ if (url.pathname === "/connect/api/run" && req.method === "POST") {
19241
+ const channel = (url.searchParams.get("channel") ?? "").replace(/[^a-z]/g, "").slice(0, 20);
19242
+ if (!channel) {
19243
+ json(res, 400, { error: "channel required" });
19244
+ return true;
19245
+ }
19246
+ if (process.platform === "darwin") execFile("osascript", [
19247
+ "-e",
19248
+ `tell application "Terminal" to do script "koi channels login ${channel}"`,
19249
+ "-e",
19250
+ "tell application \"Terminal\" to activate"
19251
+ ]);
19252
+ json(res, 200, {
19253
+ ok: true,
19254
+ command: `koi channels login ${channel}`
19255
+ });
19256
+ return true;
19257
+ }
19258
+ json(res, 404, { error: "unknown connect endpoint" });
19259
+ return true;
19260
+ } catch (err) {
19261
+ json(res, 500, { error: String(err) });
19262
+ return true;
19263
+ }
19264
+ };
19265
+ }
19266
+
19095
19267
  //#endregion
19096
19268
  //#region src/infra/gateway-lock.ts
19097
19269
  const DEFAULT_TIMEOUT_MS = 5e3;
@@ -19353,6 +19525,10 @@ async function createGatewayRuntimeState(params) {
19353
19525
  const httpBindHosts = [];
19354
19526
  for (const host of bindHosts) {
19355
19527
  const httpServer = createGatewayHttpServer({
19528
+ handleConnectRequest: createConnectPageHandler({
19529
+ bindHost: host,
19530
+ port: params.port
19531
+ }),
19356
19532
  canvasHost,
19357
19533
  clients,
19358
19534
  controlUiEnabled: params.controlUiEnabled,
package/dist/index.js CHANGED
@@ -91,11 +91,11 @@ import { t as isMainModule } from "./is-main-CQX7mFIJ.js";
91
91
  import { t as ensureSKYKOICliOnPath } from "./path-env-CnhsG0TT.js";
92
92
  import { t as assertSupportedRuntime } from "./runtime-guard-qFkyrhAB.js";
93
93
  import "./ports-B03Y1yyv.js";
94
- import "./config-guard-uL42blI1.js";
94
+ import "./config-guard-K9XgRTDS.js";
95
95
  import "./logging-C3sRv-iX.js";
96
96
  import "./note-PNq_JEQe.js";
97
97
  import "./clack-prompter-clPzQ9p-.js";
98
- import "./onboarding-CfKnJZbi.js";
98
+ import "./onboarding-sBRViahV.js";
99
99
  import "./onboard-skills-BdvkU1bg.js";
100
100
  import "./github-copilot-auth-BEsuL6VZ.js";
101
101
  import "./onboard-channels-C7E-puRC.js";
@@ -114,8 +114,8 @@ import "./systemd-DZP4s4qd.js";
114
114
  import "./diagnostics-6vXdnH8k.js";
115
115
  import "./node-service-Bb6tgGQx.js";
116
116
  import "./channels-status-issues-CGTJwSbx.js";
117
- import "./doctor-completion-Dg19Gwxi.js";
118
- import "./register.subclis-B7OaMfn1.js";
117
+ import "./doctor-completion-BQuJ38kv.js";
118
+ import "./register.subclis-D0eQnEI6.js";
119
119
  import "./gateway-rpc-DwTpsQgX.js";
120
120
  import "./help-format-Bz-E4Xsi.js";
121
121
  import "./admin-unlock-CjZRxHxf.js";
@@ -131,14 +131,14 @@ import "./ensure-local-gateway-Xk7ir7zS.js";
131
131
  import "./channel-auth-DCGvsTTl.js";
132
132
  import "./login-JCFx5Pzl.js";
133
133
  import "./auth-health-FPMBFAsj.js";
134
- import "./doctor-UXLuku1H.js";
135
- import "./completion-cli-C4vYv68z.js";
134
+ import "./doctor-Co47_2NL.js";
135
+ import "./completion-cli-CnAgvf3H.js";
136
136
  import "./service-audit-BVZGmzLW.js";
137
137
  import "./hooks-status-Cr0qf9U9.js";
138
- import "./tui-LnWEBmox.js";
138
+ import "./tui-D-n6UhuD.js";
139
139
  import "./canvas-state-C3YRnkNr.js";
140
140
  import "./channel-options-D0QGvmil.js";
141
- import { n as buildProgram } from "./program-C3gh4a7L.js";
141
+ import { n as buildProgram } from "./program-CfMxAtmt.js";
142
142
  import process from "node:process";
143
143
  import { fileURLToPath } from "node:url";
144
144
 
@@ -38,12 +38,12 @@ import { t as readLastGatewayErrorLine } from "./diagnostics-6vXdnH8k.js";
38
38
  import { t as resolveNodeService } from "./node-service-Bb6tgGQx.js";
39
39
  import { t as collectChannelStatusIssues } from "./channels-status-issues-CGTJwSbx.js";
40
40
  import { i as redactSecrets, n as formatDuration$1, r as formatGatewayAuthUsed, t as formatAge$1 } from "./format-DtciOWIX.js";
41
- import { a as formatUpdateOneLiner, i as formatUpdateAvailableHint, o as getUpdateCheckResult, r as ensureCompletionCacheExists, s as resolveUpdateAvailability, t as checkShellCompletionStatus } from "./doctor-completion-Dg19Gwxi.js";
41
+ import { a as formatUpdateOneLiner, i as formatUpdateAvailableHint, o as getUpdateCheckResult, r as ensureCompletionCacheExists, s as resolveUpdateAvailability, t as checkShellCompletionStatus } from "./doctor-completion-BQuJ38kv.js";
42
42
  import { t as ensureControlUiAssetsBuilt } from "./control-ui-assets-D4o4damy.js";
43
43
  import { a as gatewayInstallErrorHint, i as buildGatewayInstallPlan, n as GATEWAY_DAEMON_RUNTIME_OPTIONS, t as DEFAULT_GATEWAY_DAEMON_RUNTIME } from "./daemon-runtime-DIgqhoVa.js";
44
- import { r as installCompletion } from "./completion-cli-C4vYv68z.js";
44
+ import { r as installCompletion } from "./completion-cli-CnAgvf3H.js";
45
45
  import { t as buildWorkspaceHookStatus } from "./hooks-status-Cr0qf9U9.js";
46
- import { t as runTui } from "./tui-LnWEBmox.js";
46
+ import { t as runTui } from "./tui-D-n6UhuD.js";
47
47
  import fs from "node:fs";
48
48
  import path from "node:path";
49
49
  import os from "node:os";
@@ -1,5 +1,5 @@
1
1
  import { a as __toCommonJS, i as __require, o as __toESM, r as __exportAll, t as __commonJSMin } from "./chunk-D_gEzPfs.js";
2
- import { a as require_jws, i as require_dist_cjs$1, n as LRUCache$1, o as require_safe_buffer, r as getOAuthProviders, s as getEnvApiKey } from "./pi-model-discovery-ClImJtLC.js";
2
+ import { a as require_jws, i as require_dist_cjs$1, n as LRUCache$1, o as require_safe_buffer, r as getOAuthProviders, s as getEnvApiKey } from "./pi-model-discovery-lynj0LAO.js";
3
3
  import { t as require_dist_cjs$2 } from "./dist-cjs-B9iGzXDA.js";
4
4
  import { C as require_dist_cjs$3, E as init_dist_es$1, M as require_dist_cjs$13, N as require_dist_cjs$12, T as dist_es_exports$1, a as require_dist_cjs$5, c as require_dist_cjs$17, d as require_dist_cjs$15, f as dist_es_exports, h as protocols_exports, i as require_dist_cjs$7, j as require_dist_cjs$14, l as require_dist_cjs$16, m as init_protocols, n as require_dist_cjs$10, o as require_dist_cjs$8, p as init_dist_es, r as require_dist_cjs$9, s as require_dist_cjs$11, t as require_dist_cjs$18, u as require_dist_cjs$6, w as require_dist_cjs$4 } from "./dist-cjs-Cpdu8jQP.js";
5
5
  import { C as schema_exports, N as require_dist_cjs$21, P as require_dist_cjs$19, S as init_schema, t as require_dist_cjs$20 } from "./dist-cjs-BVSr8ctW.js";
@@ -21,7 +21,7 @@ import chalk, { Chalk } from "chalk";
21
21
  import fs, { constants, createWriteStream, existsSync, promises, statSync } from "node:fs";
22
22
  import path, { join } from "node:path";
23
23
  import { Logger } from "tslog";
24
- import JSON5 from "json5";
24
+ import json5 from "json5";
25
25
  import os, { homedir, tmpdir } from "node:os";
26
26
  import { promisify } from "node:util";
27
27
  import fs$1 from "node:fs/promises";
@@ -42,7 +42,7 @@ import { mkdir, readFile, stat as stat$1, unlink, writeFile } from "fs/promises"
42
42
  import { Readable as Readable$1 } from "node:stream";
43
43
  import { pipeline as pipeline$1 } from "node:stream/promises";
44
44
  import WebSocket, { WebSocket as WebSocket$1 } from "ws";
45
- import AjvPkg from "ajv";
45
+ import AjvModule from "ajv";
46
46
  import lockfile from "proper-lockfile";
47
47
  import { URL as URL$1 } from "url";
48
48
  import "yaml";
@@ -2264,7 +2264,7 @@ function readLoggingConfig() {
2264
2264
  try {
2265
2265
  if (!fs.existsSync(configPath)) return;
2266
2266
  const raw = fs.readFileSync(configPath, "utf-8");
2267
- const logging = JSON5.parse(raw)?.logging;
2267
+ const logging = json5.parse(raw)?.logging;
2268
2268
  if (!logging || typeof logging !== "object" || Array.isArray(logging)) return;
2269
2269
  return logging;
2270
2270
  } catch {
@@ -19099,7 +19099,7 @@ var IncludeProcessor = class IncludeProcessor {
19099
19099
  };
19100
19100
  const defaultResolver = {
19101
19101
  readFile: (p) => fs.readFileSync(p, "utf-8"),
19102
- parseJson: (raw) => JSON5.parse(raw)
19102
+ parseJson: (raw) => json5.parse(raw)
19103
19103
  };
19104
19104
  /**
19105
19105
  * Resolves all $include directives in a parsed config object.
@@ -20609,7 +20609,7 @@ function loadPluginManifestRegistry(params) {
20609
20609
 
20610
20610
  //#endregion
20611
20611
  //#region src/plugins/schema-validator.ts
20612
- const ajv$1 = new AjvPkg({
20612
+ const ajv$1 = new AjvModule({
20613
20613
  allErrors: true,
20614
20614
  strict: false,
20615
20615
  removeAdditional: false
@@ -21797,18 +21797,18 @@ function resolveConfigPathForDeps(deps) {
21797
21797
  function normalizeDeps(overrides = {}) {
21798
21798
  return {
21799
21799
  fs: overrides.fs ?? fs,
21800
- json5: overrides.json5 ?? JSON5,
21800
+ json5: overrides.json5 ?? json5,
21801
21801
  env: overrides.env ?? process.env,
21802
21802
  homedir: overrides.homedir ?? os.homedir,
21803
21803
  configPath: overrides.configPath ?? "",
21804
21804
  logger: overrides.logger ?? console
21805
21805
  };
21806
21806
  }
21807
- function parseConfigJson5(raw, json5 = JSON5) {
21807
+ function parseConfigJson5(raw, json5$1 = json5) {
21808
21808
  try {
21809
21809
  return {
21810
21810
  ok: true,
21811
- parsed: json5.parse(raw)
21811
+ parsed: json5$1.parse(raw)
21812
21812
  };
21813
21813
  } catch (err) {
21814
21814
  return {
@@ -22322,7 +22322,7 @@ function loadSessionStore(storePath, opts = {}) {
22322
22322
  let mtimeMs = getFileMtimeMs(storePath);
22323
22323
  try {
22324
22324
  const raw = fs.readFileSync(storePath, "utf-8");
22325
- const parsed = JSON5.parse(raw);
22325
+ const parsed = json5.parse(raw);
22326
22326
  if (isSessionStoreRecord(parsed)) store = parsed;
22327
22327
  mtimeMs = getFileMtimeMs(storePath) ?? mtimeMs;
22328
22328
  } catch {}
@@ -48256,7 +48256,7 @@ const PROTOCOL_VERSION = 3;
48256
48256
 
48257
48257
  //#endregion
48258
48258
  //#region src/gateway/protocol/index.ts
48259
- const ajv = new AjvPkg({
48259
+ const ajv = new AjvModule({
48260
48260
  allErrors: true,
48261
48261
  strict: false,
48262
48262
  removeAdditional: false
@@ -68159,7 +68159,7 @@ function enqueueSystemEvent(text, options) {
68159
68159
  const MODEL_CACHE = /* @__PURE__ */ new Map();
68160
68160
  (async () => {
68161
68161
  try {
68162
- const { discoverAuthStorage, discoverModels } = await import("./pi-model-discovery-ClImJtLC.js").then((n) => n.t);
68162
+ const { discoverAuthStorage, discoverModels } = await import("./pi-model-discovery-lynj0LAO.js").then((n) => n.t);
68163
68163
  await ensureSKYKOIModelsJson(loadConfig());
68164
68164
  const koiDir = resolveSKYKOIKoiDir();
68165
68165
  const models = discoverModels(discoverAuthStorage(koiDir), koiDir).getAll();
@@ -34,7 +34,7 @@ import { access, mkdir, readFile, stat as stat$1, writeFile } from "fs/promises"
34
34
  import Stream, { Readable as Readable$1 } from "node:stream";
35
35
  import { finished } from "node:stream/promises";
36
36
  import * as NodeWs from "ws";
37
- import AjvPkg from "ajv";
37
+ import AjvModule from "ajv";
38
38
  import lockfile from "proper-lockfile";
39
39
  import { fileURLToPath as fileURLToPath$1 } from "url";
40
40
  import { TypeCompiler } from "@sinclair/typebox/compiler";
@@ -59699,7 +59699,7 @@ var require_dist$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
59699
59699
  //#endregion
59700
59700
  //#region node_modules/.pnpm/@mariozechner+pi-ai@0.52.8_patch_hash=f41b8429247a07c256a366fc8eddb44710b4e74212f25ffaf_aba27699dbfe3dddaa7a3984ad46615e/node_modules/@mariozechner/pi-ai/dist/utils/validation.js
59701
59701
  var import_dist$1 = /* @__PURE__ */ __toESM(require_dist$1(), 1);
59702
- const Ajv$1 = AjvPkg.default || AjvPkg;
59702
+ const Ajv$1 = AjvModule.default || AjvModule;
59703
59703
  const addFormats = import_dist$1.default.default || import_dist$1.default;
59704
59704
  const isBrowserExtension = typeof globalThis !== "undefined" && globalThis.chrome?.runtime?.id !== void 0;
59705
59705
  let ajv = null;
@@ -174026,7 +174026,7 @@ var AuthStorage = class {
174026
174026
  /**
174027
174027
  * Model registry - manages built-in and custom models, provides API key resolution.
174028
174028
  */
174029
- const Ajv = AjvPkg.default || AjvPkg;
174029
+ const Ajv = AjvModule.default || AjvModule;
174030
174030
  const OpenRouterRoutingSchema = Type.Object({
174031
174031
  only: Type.Optional(Type.Array(Type.String())),
174032
174032
  order: Type.Optional(Type.Array(Type.String()))
@@ -5,10 +5,10 @@ import { n as replaceCliName, r as resolveCliName } from "./command-format-DOYW_
5
5
  import { t as isTruthyEnvValue } from "./env-C2ovlUPG.js";
6
6
  import { t as VERSION } from "./version-B_FpLmDY.js";
7
7
  import { t as formatDocsLink } from "./links-BY_N2dMU.js";
8
- import { i as registerProgramCommands, n as PLUGIN_CLI_COMMANDS, t as ensureConfigReady } from "./config-guard-uL42blI1.js";
9
- import { a as getCommandPath, d as hasHelpOrVersion, l as getVerboseFlag } from "./register.subclis-B7OaMfn1.js";
8
+ import { i as registerProgramCommands, n as PLUGIN_CLI_COMMANDS, t as ensureConfigReady } from "./config-guard-K9XgRTDS.js";
9
+ import { a as getCommandPath, d as hasHelpOrVersion, l as getVerboseFlag } from "./register.subclis-D0eQnEI6.js";
10
10
  import { t as ensurePluginRegistryLoaded } from "./plugin-registry-Dz7tFOeN.js";
11
- import { i as hasEmittedCliBanner, n as emitCliBanner, r as formatCliBannerLine } from "./tui-LnWEBmox.js";
11
+ import { i as hasEmittedCliBanner, n as emitCliBanner, r as formatCliBannerLine } from "./tui-D-n6UhuD.js";
12
12
  import { n as resolveCliChannelOptions } from "./channel-options-D0QGvmil.js";
13
13
  import { Command } from "commander";
14
14
 
@@ -124,7 +124,7 @@ const entries = [
124
124
  name: "gateway",
125
125
  description: "Gateway control",
126
126
  register: async (program) => {
127
- (await import("./gateway-cli-DQrxGX-4.js")).registerGatewayCli(program);
127
+ (await import("./gateway-cli-BpSWIzPr.js")).registerGatewayCli(program);
128
128
  }
129
129
  },
130
130
  {
@@ -201,7 +201,7 @@ const entries = [
201
201
  name: "tui",
202
202
  description: "Terminal UI",
203
203
  register: async (program) => {
204
- (await import("./tui-cli-7ccTTk2g.js")).registerTuiCli(program);
204
+ (await import("./tui-cli-DdsPOyEw.js")).registerTuiCli(program);
205
205
  }
206
206
  },
207
207
  {
@@ -317,14 +317,14 @@ const entries = [
317
317
  name: "update",
318
318
  description: "CLI update helpers",
319
319
  register: async (program) => {
320
- (await import("./update-cli-CtqXc39J.js")).registerUpdateCli(program);
320
+ (await import("./update-cli-9PXRA3S_.js")).registerUpdateCli(program);
321
321
  }
322
322
  },
323
323
  {
324
324
  name: "completion",
325
325
  description: "Generate shell completion script",
326
326
  register: async (program) => {
327
- (await import("./completion-cli-C4vYv68z.js").then((n) => n.n)).registerCompletionCli(program);
327
+ (await import("./completion-cli-CnAgvf3H.js").then((n) => n.n)).registerCompletionCli(program);
328
328
  }
329
329
  }
330
330
  ];
@@ -88,11 +88,11 @@ import "./deps-CNr0CXJR.js";
88
88
  import "./tailscale-BOh3Z_vn.js";
89
89
  import { t as ensureSKYKOICliOnPath } from "./path-env-CnhsG0TT.js";
90
90
  import { t as assertSupportedRuntime } from "./runtime-guard-qFkyrhAB.js";
91
- import { n as PLUGIN_CLI_COMMANDS, r as findRoutedCommand, t as ensureConfigReady } from "./config-guard-uL42blI1.js";
91
+ import { n as PLUGIN_CLI_COMMANDS, r as findRoutedCommand, t as ensureConfigReady } from "./config-guard-K9XgRTDS.js";
92
92
  import "./logging-C3sRv-iX.js";
93
93
  import "./note-PNq_JEQe.js";
94
94
  import "./clack-prompter-clPzQ9p-.js";
95
- import "./onboarding-CfKnJZbi.js";
95
+ import "./onboarding-sBRViahV.js";
96
96
  import "./onboard-skills-BdvkU1bg.js";
97
97
  import "./github-copilot-auth-BEsuL6VZ.js";
98
98
  import "./onboard-channels-C7E-puRC.js";
@@ -111,8 +111,8 @@ import "./systemd-DZP4s4qd.js";
111
111
  import "./diagnostics-6vXdnH8k.js";
112
112
  import "./node-service-Bb6tgGQx.js";
113
113
  import "./channels-status-issues-CGTJwSbx.js";
114
- import "./doctor-completion-Dg19Gwxi.js";
115
- import { a as getCommandPath, c as getPrimaryCommand, d as hasHelpOrVersion } from "./register.subclis-B7OaMfn1.js";
114
+ import "./doctor-completion-BQuJ38kv.js";
115
+ import { a as getCommandPath, c as getPrimaryCommand, d as hasHelpOrVersion } from "./register.subclis-D0eQnEI6.js";
116
116
  import "./gateway-rpc-DwTpsQgX.js";
117
117
  import "./help-format-Bz-E4Xsi.js";
118
118
  import "./admin-unlock-CjZRxHxf.js";
@@ -128,11 +128,11 @@ import "./ensure-local-gateway-Xk7ir7zS.js";
128
128
  import "./channel-auth-DCGvsTTl.js";
129
129
  import "./login-JCFx5Pzl.js";
130
130
  import "./auth-health-FPMBFAsj.js";
131
- import "./doctor-UXLuku1H.js";
132
- import "./completion-cli-C4vYv68z.js";
131
+ import "./doctor-Co47_2NL.js";
132
+ import "./completion-cli-CnAgvf3H.js";
133
133
  import "./service-audit-BVZGmzLW.js";
134
134
  import "./hooks-status-Cr0qf9U9.js";
135
- import { n as emitCliBanner } from "./tui-LnWEBmox.js";
135
+ import { n as emitCliBanner } from "./tui-D-n6UhuD.js";
136
136
  import "./canvas-state-C3YRnkNr.js";
137
137
  import process$1 from "node:process";
138
138
  import { fileURLToPath } from "node:url";
@@ -187,7 +187,7 @@ async function runCli(argv = process$1.argv) {
187
187
  assertSupportedRuntime();
188
188
  if (await tryRouteCli(normalizedArgv)) return;
189
189
  enableConsoleCapture();
190
- const { buildProgram } = await import("./program-C3gh4a7L.js").then((n) => n.t);
190
+ const { buildProgram } = await import("./program-CfMxAtmt.js").then((n) => n.t);
191
191
  const program = buildProgram();
192
192
  installUnhandledRejectionHandler();
193
193
  process$1.on("uncaughtException", (error) => {
@@ -224,7 +224,7 @@ async function runCli(argv = process$1.argv) {
224
224
  }
225
225
  const primary = getPrimaryCommand(parseArgv);
226
226
  if (primary) {
227
- const { registerSubCliByName } = await import("./register.subclis-B7OaMfn1.js").then((n) => n.i);
227
+ const { registerSubCliByName } = await import("./register.subclis-D0eQnEI6.js").then((n) => n.i);
228
228
  await registerSubCliByName(program, primary);
229
229
  }
230
230
  if (!!primary && PLUGIN_CLI_COMMANDS.has(primary)) {
@@ -3041,18 +3041,11 @@ function scheduleSelfUninstall(pkg = "skykoi") {
3041
3041
  * every channel — or a single one when named. Shared by classic and zen.
3042
3042
  */
3043
3043
  function openConnectTerminal(channel) {
3044
- const target = channel?.trim() ? channel.trim().toLowerCase() : "";
3045
- const cmd = target ? `koi channels login ${target}` : "koi channels login --all";
3046
- if (process.platform !== "darwin") return cmd;
3047
- try {
3048
- execFile("osascript", [
3049
- "-e",
3050
- `tell application "Terminal" to do script "${cmd.replace(/"/g, "\\\"")}"`,
3051
- "-e",
3052
- "tell application \"Terminal\" to activate"
3053
- ]);
3044
+ const url = "http://127.0.0.1:18789/connect";
3045
+ if (process.platform === "darwin") try {
3046
+ execFile("open", [url]);
3054
3047
  } catch {}
3055
- return cmd;
3048
+ return url;
3056
3049
  }
3057
3050
  function createCaptureCommands(context) {
3058
3051
  const { client, chatLog } = context;
@@ -3081,8 +3074,8 @@ function createCaptureCommands(context) {
3081
3074
  const missing = (Array.isArray(status?.channels) ? status.channels : []).filter((c) => c.configured === false || c.linked === false).map((c) => c.channel).filter(Boolean);
3082
3075
  if (missing.length > 0) chatLog.addSystem(`needs connecting: ${missing.join(", ")}`);
3083
3076
  } catch {}
3084
- const cmd = openConnectTerminal(args);
3085
- chatLog.addSystem(process.platform === "darwin" ? `opened the connection flow in a Terminal window (${cmd}) — WhatsApp shows a QR to scan, email/calendar opens sign-in links` : `run: ${cmd}`);
3077
+ const url = openConnectTerminal(args);
3078
+ chatLog.addSystem(process.platform === "darwin" ? `opened the guided connection page in your browser (${url}) — scan the WhatsApp QR there, one button per account` : `open: ${url}`);
3086
3079
  };
3087
3080
  const handlePrivate = async (args) => {
3088
3081
  try {
@@ -60,9 +60,9 @@ import "./systemd-DZP4s4qd.js";
60
60
  import "./diagnostics-6vXdnH8k.js";
61
61
  import "./daemon-runtime-DIgqhoVa.js";
62
62
  import "./ensure-local-gateway-Xk7ir7zS.js";
63
- import "./tui-LnWEBmox.js";
63
+ import "./tui-D-n6UhuD.js";
64
64
  import "./canvas-state-C3YRnkNr.js";
65
- import { t as runShell } from "./tui-shell-Cb4XwIAh.js";
65
+ import { t as runShell } from "./tui-shell-DOjzcOig.js";
66
66
 
67
67
  //#region src/cli/tui-cli.ts
68
68
  function registerTuiCli(program) {
@@ -6,7 +6,7 @@ import { O as visibleWidth } from "./dist-B01d37B6.js";
6
6
  import { D as getSlashCommands, M as readDurableDigest, T as aliasCommandsFor, c as routeFastLane, i as buildDigest, j as readConversationTurns, l as saveFastModeEnabled, o as filterAllowedCommands, s as loadFastModeEnabled, u as splitSentences, v as friendlyToolLabel } from "./ca-director-BZlhiXCn.js";
7
7
  import { c as soundConfig, i as playReplyPing, o as playSystemSound, s as setSoundConfig, u as releaseVoice } from "./channel-summary-DNu96QpK.js";
8
8
  import { s as repairSurface, t as drawZenSurface } from "./zen-surface-DJHZWAux.js";
9
- import { C as currentViewPreset, S as currentView, _ as koiFps, a as SurfacePanel, b as VIEW_PRESETS, c as createEventHandlers, d as stopSpeaking, f as openConnectTerminal, g as koiCellFrame, h as KOI_SLOT_W, l as onboardingCurrent, m as KOI_SLOT_H, o as createSurfaceSyncWatcher, p as GatewayChatClient, s as createChecklistSyncWatcher, t as runTui, u as speakChunks, v as koiFrameCount, w as setViewPreset, x as VIEW_PRESET_BLURBS, y as ChatLog } from "./tui-LnWEBmox.js";
9
+ import { C as currentViewPreset, S as currentView, _ as koiFps, a as SurfacePanel, b as VIEW_PRESETS, c as createEventHandlers, d as stopSpeaking, f as openConnectTerminal, g as koiCellFrame, h as KOI_SLOT_W, l as onboardingCurrent, m as KOI_SLOT_H, o as createSurfaceSyncWatcher, p as GatewayChatClient, s as createChecklistSyncWatcher, t as runTui, u as speakChunks, v as koiFrameCount, w as setViewPreset, x as VIEW_PRESET_BLURBS, y as ChatLog } from "./tui-D-n6UhuD.js";
10
10
  import fs from "node:fs";
11
11
  import { execFile, spawn } from "node:child_process";
12
12
  import { randomUUID } from "node:crypto";
@@ -1217,8 +1217,8 @@ async function runZen(opts) {
1217
1217
  return;
1218
1218
  }
1219
1219
  case "connect": {
1220
- const cmd = openConnectTerminal(arg);
1221
- note(process.platform === "darwin" ? "connection flow opened in a Terminal window WhatsApp shows a QR, email/calendar opens sign-in" : `run: ${cmd}`);
1220
+ const url = openConnectTerminal(arg);
1221
+ note(process.platform === "darwin" ? "guided connection page opened in your browserscan the WhatsApp QR there" : `open: ${url}`);
1222
1222
  return;
1223
1223
  }
1224
1224
  case "fastmode":
@@ -104,15 +104,15 @@ import "./service-D1-PnhZe.js";
104
104
  import "./systemd-DZP4s4qd.js";
105
105
  import "./diagnostics-6vXdnH8k.js";
106
106
  import "./channels-status-issues-CGTJwSbx.js";
107
- import { a as formatUpdateOneLiner, i as formatUpdateAvailableHint, r as ensureCompletionCacheExists, s as resolveUpdateAvailability, t as checkShellCompletionStatus } from "./doctor-completion-Dg19Gwxi.js";
108
- import "./register.subclis-B7OaMfn1.js";
107
+ import { a as formatUpdateOneLiner, i as formatUpdateAvailableHint, r as ensureCompletionCacheExists, s as resolveUpdateAvailability, t as checkShellCompletionStatus } from "./doctor-completion-BQuJ38kv.js";
108
+ import "./register.subclis-D0eQnEI6.js";
109
109
  import { t as formatHelpExamples } from "./help-format-Bz-E4Xsi.js";
110
110
  import "./control-ui-assets-D4o4damy.js";
111
111
  import "./daemon-runtime-DIgqhoVa.js";
112
112
  import "./systemd-linger-DHSd9ikR.js";
113
113
  import "./auth-health-FPMBFAsj.js";
114
- import { t as doctorCommand } from "./doctor-UXLuku1H.js";
115
- import { r as installCompletion } from "./completion-cli-C4vYv68z.js";
114
+ import { t as doctorCommand } from "./doctor-Co47_2NL.js";
115
+ import { r as installCompletion } from "./completion-cli-CnAgvf3H.js";
116
116
  import "./service-audit-BVZGmzLW.js";
117
117
  import "./shared-tNGHWtW-.js";
118
118
  import { r as runDaemonRestart } from "./daemon-cli-DdySqCD6.js";
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/bluebubbles",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI BlueBubbles channel plugin",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/copilot-proxy",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI Copilot Proxy provider plugin",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/diagnostics-otel",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI diagnostics OpenTelemetry exporter",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/discord",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI Discord channel plugin",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/feishu",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI Feishu/Lark channel plugin (community maintained by @m1heng)",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/google-antigravity-auth",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI Google Antigravity OAuth provider plugin",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/google-gemini-cli-auth",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI Gemini CLI OAuth provider plugin",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/googlechat",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI Google Chat channel plugin",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/imessage",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI iMessage channel plugin",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/line",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI LINE channel plugin",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/llm-task",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI JSON-only LLM task plugin",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/lobster",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "Lobster workflow tool plugin (typed pipelines + resumable approvals)",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026.3.413
4
+
5
+ ### Changes
6
+ - Version alignment with core SKYKOI release numbers.
7
+
3
8
  ## 2026.3.412
4
9
 
5
10
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/matrix",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI Matrix channel plugin",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/mattermost",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI Mattermost channel plugin",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/memory-core",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI core memory search plugin",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/memory-lancedb",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI LanceDB-backed long-term memory plugin with auto-recall/capture",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/minimax-portal-auth",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI MiniMax Portal OAuth provider plugin",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026.3.413
4
+
5
+ ### Changes
6
+ - Version alignment with core SKYKOI release numbers.
7
+
3
8
  ## 2026.3.412
4
9
 
5
10
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/msteams",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI Microsoft Teams channel plugin",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/nextcloud-talk",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI Nextcloud Talk channel plugin",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026.3.413
4
+
5
+ ### Changes
6
+ - Version alignment with core SKYKOI release numbers.
7
+
3
8
  ## 2026.3.412
4
9
 
5
10
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/nostr",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI Nostr channel plugin for NIP-04 encrypted DMs",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/open-prose",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "OpenProse VM skill pack plugin (slash command + telemetry).",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/signal",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI Signal channel plugin",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/slack",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI Slack channel plugin",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/telegram",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI Telegram channel plugin",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/tlon",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI Tlon/Urbit channel plugin",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026.3.413
4
+
5
+ ### Changes
6
+ - Version alignment with core SKYKOI release numbers.
7
+
3
8
  ## 2026.3.412
4
9
 
5
10
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/twitch",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI Twitch channel plugin",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026.3.413
4
+
5
+ ### Changes
6
+ - Version alignment with core SKYKOI release numbers.
7
+
3
8
  ## 2026.3.412
4
9
 
5
10
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/voice-call",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI voice-call plugin",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/whatsapp",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI WhatsApp channel plugin",
5
5
  "type": "module",
6
6
  "devDependencies": {
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026.3.413
4
+
5
+ ### Changes
6
+ - Version alignment with core SKYKOI release numbers.
7
+
3
8
  ## 2026.3.412
4
9
 
5
10
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/zalo",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI Zalo channel plugin",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026.3.413
4
+
5
+ ### Changes
6
+ - Version alignment with core SKYKOI release numbers.
7
+
3
8
  ## 2026.3.412
4
9
 
5
10
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@SKYKOI/zalouser",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SKYKOI Zalo Personal Account plugin via zca-cli",
5
5
  "type": "module",
6
6
  "dependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skykoi",
3
- "version": "2026.3.412",
3
+ "version": "2026.3.413",
4
4
  "description": "SkyKoi \u2014 Koi runtime. Multi-channel gateway CLI with RPC Koi.",
5
5
  "keywords": [
6
6
  "cli",