@linkfox-web/app-kit 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -2
- package/dist/auth-JoGZ-Tg-.d.ts +43 -0
- package/dist/chunk-5LS4UNRR.js +1 -0
- package/dist/chunk-PZOYA4II.js +2 -0
- package/dist/chunk-TU6CZIZF.js +1 -0
- package/dist/components/index.d.ts +266 -0
- package/dist/components/index.js +4 -0
- package/dist/filter-spec-BHwe1PQ-.d.ts +77 -0
- package/dist/react/index.d.ts +58 -0
- package/dist/react/index.js +1 -0
- package/dist/runtime/index.d.ts +300 -0
- package/dist/runtime/index.js +1 -0
- package/package.json +90 -3
- package/styles.css +6 -0
package/README.md
CHANGED
|
@@ -1,3 +1,45 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @linkfox-web/app-kit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
LinkFox 应用模板的公共运行时与组件。随 SDK 一起发版,模板升级依赖即可拿到最新实现。
|
|
4
|
+
|
|
5
|
+
| 子路径 | 内容 |
|
|
6
|
+
| --- | --- |
|
|
7
|
+
| `@linkfox-web/app-kit/runtime` | 登录状态机、SmartTable 客户端工厂、工作流身份判定、LinkFox OS 客户端、错误文案、筛选条件描述、导航工具;纯 TS,不读 `process.env` |
|
|
8
|
+
| `@linkfox-web/app-kit/react` | `useAuth`、`useTimeZone`、`AgentProvider` / `useAgentPageContext` |
|
|
9
|
+
| `@linkfox-web/app-kit/components` | `AppShell`、`AuthGate`、`ThemeProvider`、`DataTable`、`FilterPanel`、`TaskCard`、`TaskLog`、`StageProgress`、`ColumnPicker`、`ComboInput`、`ConfirmDialog`、`DataPagination`、`TimezoneSelect`、`UserMenu`、`AgentPanel` |
|
|
10
|
+
| `@linkfox-web/app-kit/styles.css` | Tailwind v4 `@source "./dist"`,让宿主的 Tailwind 扫描到包内类名 |
|
|
11
|
+
|
|
12
|
+
## 宿主接线
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
// lib/app-kit.ts —— 模板里唯一的接线点
|
|
16
|
+
import { configureAppKit, createSmartTable, setActiveSmartTable } from "@linkfox-web/app-kit/runtime"
|
|
17
|
+
import { smartTableConfig } from "@/linkfox.config"
|
|
18
|
+
|
|
19
|
+
export const smartTable = createSmartTable(smartTableConfig)
|
|
20
|
+
setActiveSmartTable(smartTable)
|
|
21
|
+
|
|
22
|
+
configureAppKit({
|
|
23
|
+
gatewayBaseUrl: process.env.NEXT_PUBLIC_LINKFOX_TOOL_GATEWAY!,
|
|
24
|
+
ssoBaseUrl: process.env.NEXT_PUBLIC_LINKFOX_SSO_BASE_URL!,
|
|
25
|
+
ssoClientId: process.env.NEXT_PUBLIC_LINKFOX_SSO_CLIENT_ID ?? "",
|
|
26
|
+
rewrite: process.env.NEXT_PUBLIC_TOOL_GATEWAY_REWRITE === "true",
|
|
27
|
+
apiKey: () => process.env.NEXT_PUBLIC_LINKFOX_API_KEY,
|
|
28
|
+
applicationId: process.env.NEXT_PUBLIC_APPLICATION_ID,
|
|
29
|
+
basePath: process.env.NEXT_PUBLIC_BASE_PATH,
|
|
30
|
+
})
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```css
|
|
34
|
+
/* app/globals.css */
|
|
35
|
+
@import "tailwindcss";
|
|
36
|
+
@import "@linkfox-web/app-kit/styles.css";
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`NEXT_PUBLIC_*` 必须留在模板源码里:Next 只对应用源码做静态内联,包内的 `process.env` 在构建后是 `undefined`。
|
|
40
|
+
|
|
41
|
+
## 注意
|
|
42
|
+
|
|
43
|
+
- ESM only:双格式会让模块级单例(配置、登录态)各存一份。
|
|
44
|
+
- `"use client"` 写在 `react` / `components` 两个 entry 上;`runtime` 故意不带指令。
|
|
45
|
+
- 包内自带所需的 shadcn 原语(不导出)。Context(`SidebarProvider` / `AgentProvider`)必须与使用方同住本包,宿主不要用自己那份 `components/ui/sidebar` 去套包内组件。
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** 固定 API Key 可直接访问;未配置时通过 SSO 会话访问,网关按 Authorization 自取 Key。 */
|
|
2
|
+
type AuthState = {
|
|
3
|
+
status: "loading";
|
|
4
|
+
} | {
|
|
5
|
+
status: "callback";
|
|
6
|
+
} | {
|
|
7
|
+
status: "anonymous";
|
|
8
|
+
} | {
|
|
9
|
+
status: "redirecting";
|
|
10
|
+
} | {
|
|
11
|
+
status: "error";
|
|
12
|
+
message: string;
|
|
13
|
+
action: "login" | "config";
|
|
14
|
+
} | {
|
|
15
|
+
status: "ready";
|
|
16
|
+
apiKey?: string;
|
|
17
|
+
identity: string;
|
|
18
|
+
userName: string;
|
|
19
|
+
};
|
|
20
|
+
/** 供 `useAuth`(react 子路径)订阅;直接用 `useSyncExternalStore` 时不要读 state 本身 */
|
|
21
|
+
declare function subscribeAuth(listener: () => void): () => void;
|
|
22
|
+
declare function getAuthState(): AuthState;
|
|
23
|
+
/** 初始快照:SSR 与 hydration 首帧保持一致 */
|
|
24
|
+
declare function initialAuthState(): AuthState;
|
|
25
|
+
/** 按访问方式及 SSO 身份隔离页面缓存。 */
|
|
26
|
+
declare function authIdentity(): string;
|
|
27
|
+
declare function startAuth(): void;
|
|
28
|
+
/** 优先使用固定 Key;未配置时恢复 SSO 会话(http 会话)。 */
|
|
29
|
+
declare function loadApiKey(): Promise<void>;
|
|
30
|
+
/** 整页跳转到 SSO 授权页,登录后回到 redirectUri,再由 restoreSession 回到当前页面。 */
|
|
31
|
+
declare function login(): Promise<void>;
|
|
32
|
+
declare function logout(): void;
|
|
33
|
+
/**
|
|
34
|
+
* 网关错误处理:
|
|
35
|
+
* - 会话过期(上游 invalid_token,网关会包成 200 + error 信封):清会话回登录页,提示「会话已过期,请重新登录」。
|
|
36
|
+
* - 其它 401:配了固定 Key 按 Key 失效提示(不清除 SSO 会话),否则是登录态失效,清会话后重新登录。
|
|
37
|
+
*/
|
|
38
|
+
declare function handleGatewayError(error: unknown): void;
|
|
39
|
+
declare function maskApiKey(key: string): string;
|
|
40
|
+
/** API Key 只来自模板注入的配置;缺失时由 AuthGate 走 SSO,绝不读取旧 Key cookie。 */
|
|
41
|
+
declare function getApiKey(): string | null;
|
|
42
|
+
|
|
43
|
+
export { type AuthState as A, authIdentity as a, getAuthState as b, login as c, logout as d, subscribeAuth as e, getApiKey as g, handleGatewayError as h, initialAuthState as i, loadApiKey as l, maskApiKey as m, startAuth as s };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var p;function F(t){p={...t}}function i(){if(!p)throw new Error("app-kit 未配置:请在模板的 lib/app-kit.ts 中调用 configureAppKit(),并在入口组件里 import 该文件");return p}function s(){return i().apiKey?.()?.trim()||void 0}import{isLinkfoxHttpError as u,LinkfoxHttpError as v}from"@linkfox-web/http";var _=/算力|余额不足|计费不足|套餐到期|充值|quota exceeded|insufficient balance/i,C=/invalid_token|the access token is invalid|expired or revoked/i,c="会话已过期,请重新登录";function f(t){if(!u(t))return!1;if(t.message===c)return!0;let e=typeof t.body=="string"?t.body:JSON.stringify(t.body??"");return C.test(`${t.message} ${e}`)}var x=class extends v{constructor(e,n){super({service:"app",status:0,code:e,message:n})}};function q(t){return t instanceof DOMException&&t.name==="AbortError"}function P(t){return u(t)&&t.service==="ai-tools"&&(String(t.code)==="402"||_.test(t.message))}function g(t){return u(t)&&t.service==="ai-tools"&&(String(t.code)==="401"||t.status===401)}function l(t){if(u(t)){let e=String(t.code??"");return e==="NETWORK_ERROR"?"网络请求失败,请检查网络后重试":e==="TIMEOUT"?"请求超时,请稍后重试":f(t)?c:e==="UNAUTHORIZED"?"登录已失效,请重新登录":g(t)?"工具网关鉴权失败:API Key 或登录已失效":P(t)?`算力余额不足,请前往 LinkFox 充值后重试(${t.message})`:t.message}return t instanceof Error?t.message:String(t)}var z=(t,e)=>new Promise((n,b)=>{let k=setTimeout(n,t);e?.addEventListener("abort",()=>{clearTimeout(k),b(new DOMException("Aborted","AbortError"))})});import{recordAppVisit as L}from"@linkfox-web/ai-tools/smart-table";var N="public_app_id_xxx";function R(){let t=i().applicationId?.trim();if(!(!t||t===N))return t}function E(){let t=R();if(!t)return;let e=typeof window>"u"?void 0:window.location.href;L({appId:t,appUrl:e}).catch(()=>{})}import{configure as U}from"@linkfox-web/http";import"@linkfox-web/api-user-center";var w=!1;function m(){if(w)return;let t=i();U({services:{"ai-tools":{baseURL:t.gatewayBaseUrl,apiKey:s,apiKeyHeader:t.rewrite?"Authorization":"tool-gateway-api-key"},"third-party-sso":{baseURL:t.ssoBaseUrl}}}),w=!0}import{clearSession as O}from"@linkfox-web/http";import{clearThirdPartySsoSession as D,completeThirdPartySsoRedirect as M,readThirdPartySsoSession as T,redirectToThirdPartySso as $}from"@linkfox-web/api-user-center";var K={status:"loading"},o=K,h=!1,A,y,S=new Set;function r(t){o=t,S.forEach(e=>e())}function ut(t){return S.add(t),()=>{S.delete(t)}}function ct(){return o}function dt(){return K}function pt(){return o.status==="ready"?o.identity:""}function a(){clearTimeout(y),A=void 0}function B(t){A=t.accessToken,clearTimeout(y),y=setTimeout(()=>{d()},Math.min(Math.max(t.expireAt-Date.now(),0),2147483647)),r({status:"ready",identity:`${i().ssoClientId}:${t.sub}`,userName:t.name}),E()}function ft(){if(h)return;if(h=!0,s()){d();return}m();let t=i().ssoClientId,e=()=>{if(o.status!=="ready")return;let n=T(t);(!n||n.accessToken!==A)&&d()};window.addEventListener("focus",e),document.addEventListener("visibilitychange",e),window.addEventListener("pageshow",n=>{n.persisted&&o.status==="redirecting"&&r({status:"anonymous"})}),X()}async function X(){let t=i().ssoClientId;if(t){new URLSearchParams(window.location.search).has("state")&&r({status:"callback"});try{let e=await M(t);if(e&&e.returnTo!==window.location.href){window.location.replace(e.returnTo);return}}catch(e){a(),r({status:"error",action:"login",message:l(e)});return}}await d()}async function d(){m();let t=s();if(t){a(),O(),r({status:"ready",apiKey:t,identity:"api-key",userName:"API Key 访问"});return}let e=i().ssoClientId;if(!e){a(),r({status:"error",action:"config",message:"请配置 NEXT_PUBLIC_LINKFOX_SSO_CLIENT_ID(开发使用 .env.local,构建使用 .env),然后重启或重新构建"});return}let n=T(e);if(n){B(n);return}a(),r({status:"anonymous"})}function H(){let t=i().basePath??"";return t?`${window.location.origin}${t}/`:window.location.origin}async function gt(){if(o.status!=="redirecting"){a(),r({status:"redirecting"});try{await $({clientId:i().ssoClientId,redirectUri:H()})}catch(t){r({status:"error",action:"login",message:l(t)})}}}function I(){D(i().ssoClientId),a(),r({status:"anonymous"})}function lt(t){if(f(t)){if(o.status!=="ready")return;I(),r({status:"error",action:"login",message:c});return}if(!(!g(t)||o.status!=="ready")){if(s()){a(),r({status:"error",action:"config",message:"API Key 已失效,请更新 NEXT_PUBLIC_LINKFOX_API_KEY 后重启开发服务或重新构建部署"});return}I(),r({status:"error",action:"login",message:"登录已失效,请重新登录"})}}function mt(t){return t.length<=8?"****":`${t.slice(0,4)}****${t.slice(-4)}`}function yt(){return s()??null}export{F as a,i as b,s as c,c as d,f as e,x as f,q as g,P as h,g as i,l as j,z as k,R as l,E as m,m as n,ut as o,ct as p,dt as q,pt as r,ft as s,d as t,gt as u,I as v,lt as w,mt as x,yt as y};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{o as g,p as l,q as c}from"./chunk-5LS4UNRR.js";import{useSyncExternalStore as f}from"react";var s="linkfox:timezone",u=new Set;function T(){return Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}function m(){try{return localStorage.getItem(s)}catch{return null}}function x(){return m()||T()}function p(t){u.add(t);let e=r=>{r.key===s&&t()};return window.addEventListener("storage",e),()=>{u.delete(t),window.removeEventListener("storage",e)}}function Z(t){try{t?localStorage.setItem(s,t):localStorage.removeItem(s)}catch{}u.forEach(e=>e())}function R(){return f(p,x,()=>"UTC")}function v(){return f(p,()=>m()===null,()=>!0)}function O(t,e=new Date){try{return new Intl.DateTimeFormat("en-US",{timeZone:t,timeZoneName:"longOffset"}).formatToParts(e).find(n=>n.type==="timeZoneName")?.value.replace("GMT","UTC")||"UTC"}catch{return""}}function w(t){if(t instanceof Date)return t;if(typeof t=="number")return new Date(t);let e=String(t).trim();return/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}(:\d{2})?$/.test(e)?new Date(`${e.replace(" ","T")}Z`):/^\d{4}-\d{2}-\d{2}$/.test(e)?new Date(`${e}T00:00:00Z`):new Date(e)}function d(t,e){let r=new Intl.DateTimeFormat("en-US",{timeZone:t,hourCycle:"h23",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}).formatToParts(new Date(e)),n=o=>Number(r.find(i=>i.type===o)?.value);return Date.UTC(n("year"),n("month")-1,n("day"),n("hour"),n("minute"),n("second"))-e}function k(t,e,r=0){let[n,o,i]=t.split("-").map(Number),a=Date.UTC(n,o-1,i+r),b=a-d(e,a);return a-d(e,b)}function U(t,e){if(t==null||t==="")return"-";let r=w(t);return!r||Number.isNaN(r.getTime())?String(t):new Intl.DateTimeFormat("zh-CN",{timeZone:e,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}).format(r)}import{createContext as y,useContext as C,useEffect as h,useMemo as D,useState as A}from"react";import{jsx as E}from"react/jsx-runtime";var F="linkfox:agent-done",P=200,S=y(null);function L({children:t}){let[e,r]=A(!1),[n,o]=A(null),i=D(()=>({open:e,setOpen:r,page:n,setPage:o}),[e,n]);return E(S.Provider,{value:i,children:t})}function N(){let t=C(S);if(!t)throw new Error("useAgent 必须在 AgentProvider 内使用");return t}function G(t){let{setPage:e}=N(),r=t?JSON.stringify(t):"";h(()=>{e(r?JSON.parse(r):null)},[r,e]),h(()=>()=>e(null),[e])}function J(t,e,r){if(!e)return t;let n=["【页面上下文(系统自动带入)】",`当前页面:${e.source}`];if(e.table&&(r&&n.push(`多维表格:${r.name}(notebookId: ${r.notebookId})`),n.push(`数据表:${e.table.name}(tableId: ${e.table.id})`),n.push("读写数据请用 linkfox-smart-table 技能操作上述数据表,修改前确认字段名存在。")),e.records.length){let o=e.records.slice(0,P);n.push(`用户勾选的记录(${e.records.length} 条,格式:${e.idLabel??"recordId"} | 摘要):`),o.forEach(i=>n.push(`- ${i.id} | ${i.label}`)),e.records.length>o.length&&n.push(`(其余 ${e.records.length-o.length} 条未列出)`)}return n.push("","【用户要求】",t),n.join(`
|
|
2
|
+
`)}var z=(t,e=60)=>t.length>e?`${t.slice(0,e)}…`:t;import{useSyncExternalStore as $}from"react";function Y(){return $(g,l,c)}export{T as a,Z as b,R as c,v as d,O as e,k as f,U as g,F as h,L as i,N as j,G as k,J as l,z as m,Y as n};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{f as D,g as M,h as K,i as G,k as V,r as $,w as L}from"./chunk-5LS4UNRR.js";function ct(t){return t.type==="range"||t.type==="dateRange"?[`${t.id}.gte`,`${t.id}.lte`]:[t.id]}function W(t){return(t??"").split(",").map(e=>e.trim()).filter(Boolean)}function dt(t,e,l){let s=W(t).filter(f=>f!==e);return l&&s.push(e),s.join(",")}function ut(t,e){for(let l of t){let s=l.items.find(f=>e===f.href||e.startsWith(`${f.href}/`));if(s)return{group:l,item:s}}return null}async function v(t){try{return await t}catch(e){throw L(e),e}}import*as w from"@linkfox-web/ai-tools/agent-os";var Y=2500,z=5,J=3,ht=[{id:"default",name:"通用助手"},{id:"linkfox-product-selection-agent",name:"选品 Agent"},{id:"linkfox-market-analysis-agent",name:"市场分析 Agent"},{id:"linkfox-listing-agent",name:"Listing Agent"},{id:"linkfox-image-agent",name:"图片 Agent"},{id:"linkfox-video-agent",name:"视频 Agent"}],Z={read:"读取文件",execute:"执行命令",edit:"编辑文件",search:"搜索"},j=t=>t?.type==="text"||t?.type===void 0?t?.text??t?.value??"":"";function tt(t){return t.type!=="resource_link"||!t.uri?null:{name:decodeURIComponent(t.uri.split("?")[0].split("/").pop()??"")||t.name||"文件",uri:t.uri}}function et(t){let e=new Map,l="";return t.forEach((s,f)=>{if(s.sessionUpdate==="tool_call"||s.sessionUpdate==="tool_call_update"){let u=s.toolCallId??`step-${f}`,b=e.get(u),I=s.title?.replace(/\(.*\)$/,"")||b?.title||Z[s.kind??""]||"处理中",x=s.status==="completed"?"done":s.status==="failed"?"failed":b?.status??"running";e.set(u,{id:u,title:I,status:x})}else(s.sessionUpdate==="agent_message_chunk"||s.sessionUpdate==null)&&(l+=j(s.content))}),{steps:[...e.values()],text:l}}function nt(t){let e="",l=new Map;for(let{content:s}of t){if(!s)continue;let f=tt(s);f?l.set(f.uri,f):e+=j(s)}return{text:e,files:[...l.values()]}}function wt(t){return v(w.cancelTask({messageId:t}))}async function It(t){try{return(await v(w.getShareUrl({messageId:t}))).shareUrl||void 0}catch{return}}async function xt(t,e,{signal:l,onUpdate:s,sessionId:f}){let u=await v(w.createTask(f?{prompt:t,modelId:e,sessionId:f}:{prompt:t,modelId:e},{signal:l}));if(!u.id)throw new D(500,"LinkFox OS 没有返回任务 ID");let b=u.id,I=u.sessionId||f||"";s({messageId:b,sessionId:I,steps:[],text:"",files:[],stopReason:""});let x=new Map,T=0,N=0;for(;;){await V(Y,l);let O=Math.max(0,T-z),y;try{y=await v(w.getTask({messageId:b,fromIndex:O},{signal:l})),N=0}catch(p){if(M(p)||G(p)||K(p)||++N>=J)throw p;continue}y.eventList?.forEach((p,R)=>x.set(O+R,p)),T=y.eventTotal??T;let C=[...x.entries()].sort((p,R)=>p[0]-R[0]).map(([,p])=>p),F=et(C),P=y.message?.stopReason??"";if(P){let p=nt(y.message?.agentMessageChunks??[]),R=F.steps.map(E=>E.status==="running"?{...E,status:"done"}:E);return{messageId:b,sessionId:I,steps:R,text:p.text||F.text,files:p.files,stopReason:P}}s({messageId:b,sessionId:I,steps:F.steps,text:F.text,files:[],stopReason:""})}}import{LinkfoxHttpError as rt}from"@linkfox-web/http";import*as d from"@linkfox-web/ai-tools/smart-table";function A(t,e){return new rt({service:"ai-tools",status:200,code:t,message:e})}var q=(t,e)=>(t.createdTime??"").localeCompare(e.createdTime??""),H=t=>Object.fromEntries(t.map(e=>[e.name,e.fieldId]));function X(t,e,l){let s=t.get(e);return s||(s=l(),t.set(e,s),s.catch(()=>t.delete(e))),s}function st(){return typeof window>"u"?!1:/(^|\.)app\.linkfox\.com$/.test(window.location.hostname)}var ot=new Set(["主图"]);function St(t){let e=t.fields??{},l=new Map,s=new Map,f=new Map;async function u(r){try{return await r}catch(o){throw L(o),o}}async function b(r){let o=[];for(let n=1;n<=50;n++){let a=await u(d[r]({page:n,perPage:100})),i=a.notebooks??[];if(o.push(...i),i.length===0||o.length>=(a.total??0))break}return o}async function I(){let{notebookId:r,notebookName:o}=t,n=await b("listMyTables");if(r){let k=n.find(h=>h.notebookId===r)??(await b("listSharedTables")).find(h=>h.notebookId===r);if(!k)throw A(404,`找不到配置的多维表 ${r},请检查 .env 的 NEXT_PUBLIC_NOTE_BOOK_ID 或 linkfox.config.ts`);return k}if(st())throw A(500,"应用未绑定多维表(缺少 NEXT_PUBLIC_NOTE_BOOK_ID)。请重新打开应用完成初始化后再试。");let a=n.filter(k=>k.name===o).sort(q);if(a.length)return a[0];let i=(await b("listSharedTables")).filter(k=>k.name===o).sort(q);if(i.length)return i[0];let m=t.requestKeyPrefix??"linkfox-app",g=await u(d.createTable({name:o,requestKey:`${m}-${o}`}));return{notebookId:g.notebookId,name:g.notebookName,tables:[{tableId:g.tableId,name:g.name,url:g.url,refKey:g.refKey}]}}function x(){return X(l,$(),I)}function T(r,o){return X(s,`${$()}:${r}`,async()=>{let n=o??e[r];if(!n)throw A(500,`数据表 ${String(r)} 没有登记列定义,请在 linkfox.config.ts 的 smartTableConfig.fields 里补上`);let a=t.tables[r];if(!a)throw A(500,`数据表 ${String(r)} 没有登记表名,请在 smartTableConfig.tables 里补上`);let i=await x(),m=i.tables.find(c=>c.name===a);if(!m){let c=await u(d.addTable({notebookId:i.notebookId,name:a,fields:n})),S={tableId:c.tableId,name:c.name,url:c.url,refKey:c.refKey};return i.tables.push(S),{...S,fieldIds:H(c.fields??[])}}let{fields:g}=await u(d.listFields({tableId:m.tableId,includeChoices:!1})),k=n.filter(c=>ot.has(c.name)&&g.some(S=>S.name===c.name&&S.type!==c.type)),h=g;if(k.length){let c=k.map(_=>_.name);h=(await u(d.deleteFields({tableId:m.tableId,fieldNames:c,allowBreakingDependents:!0}))).fields??g.filter(_=>!c.includes(_.name))}let Q=new Set(h.map(c=>c.name)),B=n.filter(c=>!Q.has(c.name));for(let c=0;c<B.length;c+=50)h=(await u(d.addFields({tableId:m.tableId,fields:B.slice(c,c+50)}))).fields??h;return{...m,fieldIds:H(h)}})}function N(r){return u(d.listRecords(r))}async function O(r,o=100){let n=[];for(let a=1;a<=o;a++){let i=await N({...r,page:a,perPage:100});if(n.push(...i.records),i.records.length<100||n.length>=i.total)break}return n}async function y(r,o){let n=[];for(let a=0;a<o.length;a+=50){let i=o.slice(a,a+50),m=await u(d.createRecords({tableId:r,records:i.map(g=>({fields:g}))}));if(n.push(...m.records??[]),m.created!==i.length)throw A(500,`已写入 ${n.length} 条,但有 ${i.length-m.created} 条未写入成功`)}return n}async function C(r,o){for(let n=0;n<o.length;n+=100){let a=o.slice(n,n+100),i=await u(d.updateRecords({tableId:r,records:a}));if(i.updated!==a.length)throw A(404,`只更新了 ${i.updated}/${a.length} 条,记录可能已被删除,请刷新后重试`)}}async function F(r,o){for(let n=0;n<o.length;n+=100)await u(d.deleteRecords({tableId:r,recordIds:o.slice(n,n+100)}))}function P(r,o,n,a){let i=`${r}:${o}:${n}`,g=(f.get(i)??Promise.resolve()).catch(()=>{}).then(()=>u(d.uploadAttachment({tableId:r,recordId:o,fieldName:n,imageUrl:a})).then(k=>k.attachment));return f.set(i,g),g.finally(()=>{f.get(i)===g&&f.delete(i)}).catch(()=>{}),g}async function p(r,o,n,a,i){return(await N({tableId:r,perPage:100,fieldNames:i,filter:{conditions:[{fieldName:o,operator:"is",value:n}]}})).records.find(g=>g.recordId===a)??null}function R(){return Promise.all(Object.keys(e).map(r=>T(r)))}async function E(r){return(await T(r)).tableId}return{config:t,TABLE_FIELDS:e,getNotebook:x,ensureTable:T,listRecords:N,listAllRecords:O,createRecords:y,updateRecords:C,deleteRecords:F,uploadAttachment:P,getRecord:p,warmTables:R,tableIdOf:E}}var U;function Nt(t){U=t}function Ft(){if(!U)throw new Error("app-kit 未注册多维表客户端:请在模板的 lib/app-kit.ts 里调用 setActiveSmartTable()");return U}function it(t){return Array.isArray(t)&&t.every(e=>e&&typeof e=="object"&&"token"in e)}function at(t){return it(t)?t[0]:void 0}function At(t,e="full"){let l=at(t);return l&&(e==="thumb"?l.smThumbnailUrl??l.lgThumbnailUrl??l.presignedUrl:l.presignedUrl)||void 0}var lt=t=>t==null?"":typeof t=="string"?t:String(t),Et=t=>typeof t=="number"?t:Number(t)||0,vt=t=>lt(t).split(/[,,、\n]/).map(e=>e.trim()).filter(Boolean),Ot=()=>new Date().toISOString();export{ct as a,W as b,dt as c,ut as d,v as e,ht as f,wt as g,It as h,xt as i,St as j,Nt as k,Ft as l,it as m,at as n,At as o,lt as p,Et as q,vt as r,Ot as s};
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { JSX } from 'react';
|
|
3
|
+
import { N as NavGroup, U as UiFilterSpec, F as FilterValues } from '../filter-spec-BHwe1PQ-.js';
|
|
4
|
+
export { a as NavItem, f as findNav } from '../filter-spec-BHwe1PQ-.js';
|
|
5
|
+
import { ThemeProvider as ThemeProvider$1 } from 'next-themes';
|
|
6
|
+
import 'lucide-react';
|
|
7
|
+
|
|
8
|
+
interface AgentSuggestions {
|
|
9
|
+
/** 按页面 source 结尾匹配的推荐提问 */
|
|
10
|
+
items: {
|
|
11
|
+
match: string;
|
|
12
|
+
items: string[];
|
|
13
|
+
}[];
|
|
14
|
+
/** 没匹配到页面时的通用提问 */
|
|
15
|
+
fallback: string[];
|
|
16
|
+
placeholder?: string;
|
|
17
|
+
}
|
|
18
|
+
interface AppShellProps {
|
|
19
|
+
children: React.ReactNode;
|
|
20
|
+
/** 左侧多级菜单,由模板的 lib/nav.ts 提供 */
|
|
21
|
+
nav: NavGroup[];
|
|
22
|
+
appName?: string;
|
|
23
|
+
appSubtitle?: string;
|
|
24
|
+
/** 左上角版本号,通常取模板 linkfox.config.ts 的 APP_VERSION */
|
|
25
|
+
version?: string;
|
|
26
|
+
/** 右上角 LinkFox OS 助手的推荐提问 */
|
|
27
|
+
suggestions?: AgentSuggestions;
|
|
28
|
+
}
|
|
29
|
+
declare function AppShell({ children, nav, appName, appSubtitle, version, suggestions }: AppShellProps): react.JSX.Element;
|
|
30
|
+
|
|
31
|
+
interface AppSidebarProps {
|
|
32
|
+
/** 左侧多级菜单,由模板的 lib/nav.ts 提供 */
|
|
33
|
+
nav: NavGroup[];
|
|
34
|
+
appName?: string;
|
|
35
|
+
appSubtitle?: string;
|
|
36
|
+
/** 左上角版本号,通常取模板 linkfox.config.ts 的 APP_VERSION */
|
|
37
|
+
version?: string;
|
|
38
|
+
}
|
|
39
|
+
/** 多级菜单:菜单组可折叠,展开后显示组内页面 */
|
|
40
|
+
declare function AppSidebar({ nav, appName, appSubtitle, version }: AppSidebarProps): react.JSX.Element;
|
|
41
|
+
|
|
42
|
+
declare function AuthGate({ children }: {
|
|
43
|
+
children: React.ReactNode;
|
|
44
|
+
}): string | number | bigint | boolean | Iterable<react.ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<react.ReactNode> | null | undefined> | react.JSX.Element | null | undefined;
|
|
45
|
+
|
|
46
|
+
declare function ThemeProvider({ children, ...props }: react.ComponentProps<typeof ThemeProvider$1>): react.JSX.Element;
|
|
47
|
+
|
|
48
|
+
declare function TimezoneSelect(): react.JSX.Element;
|
|
49
|
+
|
|
50
|
+
declare function UserMenu(): react.JSX.Element | null;
|
|
51
|
+
|
|
52
|
+
interface DataColumn<Extra = unknown> {
|
|
53
|
+
key: string;
|
|
54
|
+
label: string;
|
|
55
|
+
/**
|
|
56
|
+
* 列宽(px)。宽度不够时单元格内容会溢到相邻列(日期、徽章这类 nowrap 内容尤甚),
|
|
57
|
+
* 所以调用方要按内容给足:日期约 170、状态徽章约 104、长文本 220 以上。
|
|
58
|
+
*/
|
|
59
|
+
width?: number;
|
|
60
|
+
/** 调用方自己的列定义,renderCell 里可以取用 */
|
|
61
|
+
column?: Extra;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* 列表通用表格:列宽按内容给定,总宽超过容器时横向滚动,操作列吸在右侧。
|
|
65
|
+
*
|
|
66
|
+
* - 不用 `table-fixed` 均分:列一多(线索库默认 18 列)会把每列压到几十像素,
|
|
67
|
+
* `2026/10/30 13:48:08` 这类 nowrap 内容直接压到操作列上
|
|
68
|
+
* - 表头 + 单元格按词断行(break-words),长文本折行、窄屏不撑破行
|
|
69
|
+
* - 窄屏(< 1024px)整行转卡片纵向堆叠,列名用 data-label 生成,不改 DOM 结构
|
|
70
|
+
*
|
|
71
|
+
* 勾选、行操作、加载骨架都由调用方以 render 函数传入,组件本身不认业务字段。
|
|
72
|
+
*/
|
|
73
|
+
declare function DataTable<T, Extra = unknown>({ columns, rows, rowKey, renderCell, actions, actionsWidth, selection, onRowClick, loading, skeletonRows, empty, className, }: {
|
|
74
|
+
columns: DataColumn<Extra>[];
|
|
75
|
+
rows: T[];
|
|
76
|
+
rowKey: (row: T) => string;
|
|
77
|
+
renderCell: (row: T, column: DataColumn<Extra>) => React.ReactNode;
|
|
78
|
+
/** 行末操作列;不传则不出操作列 */
|
|
79
|
+
actions?: (row: T) => React.ReactNode;
|
|
80
|
+
actionsWidth?: number;
|
|
81
|
+
selection?: {
|
|
82
|
+
selected: Set<string>;
|
|
83
|
+
onToggleRow: (row: T, on: boolean) => void;
|
|
84
|
+
onToggleAll: (on: boolean) => void;
|
|
85
|
+
pageAllSelected: boolean;
|
|
86
|
+
pageSomeSelected: boolean;
|
|
87
|
+
};
|
|
88
|
+
onRowClick?: (row: T) => void;
|
|
89
|
+
loading?: boolean;
|
|
90
|
+
skeletonRows?: number;
|
|
91
|
+
empty?: React.ReactNode;
|
|
92
|
+
className?: string;
|
|
93
|
+
}): react.JSX.Element;
|
|
94
|
+
|
|
95
|
+
declare const PAGE_SIZE = 20;
|
|
96
|
+
declare function DataPagination({ page, total, disabled, onChange, pageSize, note, }: {
|
|
97
|
+
page: number;
|
|
98
|
+
total: number;
|
|
99
|
+
disabled?: boolean;
|
|
100
|
+
onChange: (page: number) => void;
|
|
101
|
+
/** 第三方接口自带分页下限时传入(Keepa perPage 最小 50) */
|
|
102
|
+
pageSize?: number;
|
|
103
|
+
note?: React.ReactNode;
|
|
104
|
+
}): react.JSX.Element;
|
|
105
|
+
|
|
106
|
+
/** 搜索条件面板:常用条件直接展示,不常用的折叠到“更多条件” */
|
|
107
|
+
declare function FilterPanel({ primary, more, values, onChange, onSearch, onReset, loading, currency, searchLabel, searchIcon, disabled, prepend, append, note, }: {
|
|
108
|
+
primary: UiFilterSpec[];
|
|
109
|
+
more: UiFilterSpec[];
|
|
110
|
+
values: FilterValues;
|
|
111
|
+
onChange: (values: FilterValues) => void;
|
|
112
|
+
onSearch: () => void;
|
|
113
|
+
onReset: () => void;
|
|
114
|
+
loading: boolean;
|
|
115
|
+
currency?: string;
|
|
116
|
+
searchLabel?: string;
|
|
117
|
+
searchIcon?: React.ReactNode;
|
|
118
|
+
disabled?: boolean;
|
|
119
|
+
/** 放在常用条件最前 / 最后的自定义字段 */
|
|
120
|
+
prepend?: React.ReactNode;
|
|
121
|
+
append?: React.ReactNode;
|
|
122
|
+
note?: React.ReactNode;
|
|
123
|
+
}): react.JSX.Element;
|
|
124
|
+
|
|
125
|
+
interface ComboOption {
|
|
126
|
+
value: string;
|
|
127
|
+
label?: string;
|
|
128
|
+
}
|
|
129
|
+
/** 下拉选择 + 支持手工输入 */
|
|
130
|
+
declare function ComboInput({ id, value, onChange, options, placeholder, multiple, }: {
|
|
131
|
+
id?: string;
|
|
132
|
+
value: string;
|
|
133
|
+
onChange: (value: string) => void;
|
|
134
|
+
options: readonly ComboOption[];
|
|
135
|
+
placeholder?: string;
|
|
136
|
+
/** 多选:选项追加到已有值后面(逗号分隔),已有的不重复追加 */
|
|
137
|
+
multiple?: boolean;
|
|
138
|
+
}): react.JSX.Element;
|
|
139
|
+
|
|
140
|
+
declare function ColumnPicker({ columns, visible, onChange, onReset, }: {
|
|
141
|
+
columns: {
|
|
142
|
+
key: string;
|
|
143
|
+
label: string;
|
|
144
|
+
}[];
|
|
145
|
+
visible: string[];
|
|
146
|
+
onChange: (visible: string[]) => void;
|
|
147
|
+
onReset: () => void;
|
|
148
|
+
}): react.JSX.Element;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* 高风险操作的二次确认。
|
|
152
|
+
*
|
|
153
|
+
* 默认行为就是「标题 + 说明 + 取消/确认」;高风险场景(批量删除、下单、上架)传 `details`
|
|
154
|
+
* 列出影响范围,并设 `requireCheck` 让用户主动勾选后才能继续——避免回车/误点直接执行。
|
|
155
|
+
*/
|
|
156
|
+
declare function ConfirmDialog({ open, onOpenChange, title, description, details, requireCheck, confirmLabel, cancelLabel, destructive, busy, onConfirm, }: {
|
|
157
|
+
open: boolean;
|
|
158
|
+
onOpenChange: (open: boolean) => void;
|
|
159
|
+
title: React.ReactNode;
|
|
160
|
+
description?: React.ReactNode;
|
|
161
|
+
/** 影响范围:条数、金额、目标店铺等,逐条列出 */
|
|
162
|
+
details?: React.ReactNode[];
|
|
163
|
+
/** 需要用户主动勾选「我已确认」才能继续 */
|
|
164
|
+
requireCheck?: string;
|
|
165
|
+
confirmLabel?: string;
|
|
166
|
+
cancelLabel?: string;
|
|
167
|
+
destructive?: boolean;
|
|
168
|
+
busy?: boolean;
|
|
169
|
+
onConfirm: () => void;
|
|
170
|
+
}): react.JSX.Element;
|
|
171
|
+
|
|
172
|
+
/** 阶段通过情况:一行一个阶段,label 如「G1 新品初筛」 */
|
|
173
|
+
interface TaskCardStage {
|
|
174
|
+
key: string;
|
|
175
|
+
label: string;
|
|
176
|
+
pass: number;
|
|
177
|
+
input: number;
|
|
178
|
+
todo?: number;
|
|
179
|
+
}
|
|
180
|
+
/** 算力 / 预算消耗:used 与 estimate 同单位,unit 为展示后缀 */
|
|
181
|
+
interface TaskCardBudget {
|
|
182
|
+
used: number;
|
|
183
|
+
estimate?: number;
|
|
184
|
+
unit?: string;
|
|
185
|
+
}
|
|
186
|
+
interface TaskCardData {
|
|
187
|
+
/** 唯一键,通常 recordId */
|
|
188
|
+
id: string;
|
|
189
|
+
/** 业务编号,如任务ID */
|
|
190
|
+
code: string;
|
|
191
|
+
status: string;
|
|
192
|
+
stage?: string;
|
|
193
|
+
rounds?: number;
|
|
194
|
+
budget?: TaskCardBudget;
|
|
195
|
+
/** 已按所选时区格式化好的时间,组件不碰时区 */
|
|
196
|
+
startedAt?: string;
|
|
197
|
+
lastActiveAt?: string;
|
|
198
|
+
/** 一行摘要:类目 · 站点 之类 */
|
|
199
|
+
hint?: string;
|
|
200
|
+
stages?: TaskCardStage[];
|
|
201
|
+
}
|
|
202
|
+
/** 正在跑的状态(各应用文案不同,调用方判断后传入 running) */
|
|
203
|
+
declare function TaskCard({ task, running, onOpen, onStop, onRetry, className, }: {
|
|
204
|
+
task: TaskCardData;
|
|
205
|
+
running?: boolean;
|
|
206
|
+
onOpen?: () => void;
|
|
207
|
+
onStop?: () => void;
|
|
208
|
+
onRetry?: () => void;
|
|
209
|
+
className?: string;
|
|
210
|
+
}): react.JSX.Element;
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* 任务表的「工作流执行日志」:每个阶段接手、轮次结束、失败、写入数据表失败都会追加一行。
|
|
214
|
+
* 时间戳按用户所选时区渲染;内容区带滚动条,跟随刷新自动滚到底部。
|
|
215
|
+
*/
|
|
216
|
+
declare function TaskLog({ text, timeZone, className }: {
|
|
217
|
+
text: unknown;
|
|
218
|
+
timeZone: string;
|
|
219
|
+
className?: string;
|
|
220
|
+
}): react.JSX.Element;
|
|
221
|
+
|
|
222
|
+
type StageNodeState = "done" | "active" | "idle";
|
|
223
|
+
interface StageCounts {
|
|
224
|
+
input: number;
|
|
225
|
+
pass: number;
|
|
226
|
+
fail: number;
|
|
227
|
+
todo: number;
|
|
228
|
+
}
|
|
229
|
+
interface StageNode<K extends string = string> {
|
|
230
|
+
key: K;
|
|
231
|
+
label: string;
|
|
232
|
+
}
|
|
233
|
+
/** 本闸输入数应该等于通过数 + 不通过数 + 未完成数(规则文档 6.3 的验收口径) */
|
|
234
|
+
declare function countsBalanced(c: StageCounts): boolean;
|
|
235
|
+
/**
|
|
236
|
+
* 多阶段进度条:启动条件 → 各阶段 → 产出。
|
|
237
|
+
* 点节点切换下方的明细表;每个节点显示输入 / 通过 / 不通过 / 未完成四个数。
|
|
238
|
+
* 阶段、计数、状态都由调用方按业务字段算好传入,组件本身不认字段名。
|
|
239
|
+
*/
|
|
240
|
+
declare function StageProgress<K extends string>({ startLabel, startSummary, stages, countsOf, stateOf, current, onSelect, tail, }: {
|
|
241
|
+
startLabel?: string;
|
|
242
|
+
startSummary: React.ReactNode;
|
|
243
|
+
stages: StageNode<K>[];
|
|
244
|
+
countsOf: (key: K) => StageCounts;
|
|
245
|
+
stateOf: (key: K) => StageNodeState;
|
|
246
|
+
current: K;
|
|
247
|
+
onSelect: (key: K) => void;
|
|
248
|
+
/** 末尾的产出节点(如「线索」「选品库」) */
|
|
249
|
+
tail?: {
|
|
250
|
+
label: string;
|
|
251
|
+
summary: React.ReactNode;
|
|
252
|
+
icon?: React.ReactNode;
|
|
253
|
+
};
|
|
254
|
+
}): react.JSX.Element;
|
|
255
|
+
|
|
256
|
+
declare function AgentPanel({ suggestions }: {
|
|
257
|
+
suggestions?: AgentSuggestions;
|
|
258
|
+
}): react.JSX.Element;
|
|
259
|
+
/** 顶栏按钮 */
|
|
260
|
+
declare function AgentToggle(): react.JSX.Element;
|
|
261
|
+
|
|
262
|
+
declare function Markdown({ children }: {
|
|
263
|
+
children: string;
|
|
264
|
+
}): JSX.Element;
|
|
265
|
+
|
|
266
|
+
export { AgentPanel, type AgentSuggestions, AgentToggle, AppShell, type AppShellProps, AppSidebar, type AppSidebarProps, AuthGate, ColumnPicker, ComboInput, type ComboOption, ConfirmDialog, type DataColumn, DataPagination, DataTable, FilterPanel, Markdown, NavGroup, PAGE_SIZE, type StageCounts, type StageNode, type StageNodeState, StageProgress, TaskCard, type TaskCardBudget, type TaskCardData, type TaskCardStage, TaskLog, ThemeProvider, TimezoneSelect, UserMenu, countsBalanced };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use client";import{a as ia,b as sa,c as la,d as Ee,f as Tt,g as fa,h as ga,i as ba,l as va}from"../chunk-TU6CZIZF.js";import{a as It,b as xa,c as ha,d as Ca,e as ot,h as ya,i as wa,j as zt,l as Na,n as rt}from"../chunk-PZOYA4II.js";import{g as ra,j as na,s as da,t as ca,u as pa,v as ma,x as ua}from"../chunk-5LS4UNRR.js";import{Fragment as Gn}from"react";import Fn from"next/link";import{usePathname as On}from"next/navigation";import Lt from"next/link";import{usePathname as Ur}from"next/navigation";import{ChevronRightIcon as Zr}from"lucide-react";import{Collapsible as Dt}from"radix-ui";import{jsx as At}from"react/jsx-runtime";function ge({...e}){return At(Dt.Root,{"data-slot":"collapsible",...e})}function be({...e}){return At(Dt.CollapsibleTrigger,{"data-slot":"collapsible-trigger",...e})}function ve({...e}){return At(Dt.CollapsibleContent,{"data-slot":"collapsible-content",...e})}import*as M from"react";import{cva as Er}from"class-variance-authority";import{cn as I}from"cn";import{Slot as _a}from"radix-ui";import*as Pa from"react";var vr=768,ka=`(max-width: ${vr-1}px)`;function xr(e){let t=window.matchMedia(ka);return t.addEventListener("change",e),()=>t.removeEventListener("change",e)}function Sa(){return Pa.useSyncExternalStore(xr,()=>window.matchMedia(ka).matches,()=>!1)}import{cva as hr}from"class-variance-authority";import{cn as Cr}from"cn";import{Slot as yr}from"radix-ui";import{jsx as Nr}from"react/jsx-runtime";var wr=hr("group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",{variants:{variant:{default:"bg-primary text-primary-foreground hover:bg-primary/80",outline:"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",secondary:"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",ghost:"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",destructive:"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",link:"text-primary underline-offset-4 hover:underline"},size:{default:"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",xs:"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",sm:"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",lg:"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",icon:"size-8","icon-xs":"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3","icon-sm":"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg","icon-lg":"size-9"}},defaultVariants:{variant:"default",size:"default"}});function p({className:e,variant:t="default",size:a="default",asChild:o=!1,...r}){let i=o?yr.Root:"button";return Nr(i,{"data-slot":"button","data-variant":t,"data-size":a,className:Cr(wr({variant:t,size:a,className:e})),...r})}import{cn as Pr}from"cn";import{jsx as kr}from"react/jsx-runtime";function te({className:e,type:t,...a}){return kr("input",{type:t,"data-slot":"input",className:Pr("h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",e),...a})}import{cn as Sr}from"cn";import{Separator as Rr}from"radix-ui";import{jsx as Tr}from"react/jsx-runtime";function Ra({className:e,orientation:t="horizontal",decorative:a=!0,...o}){return Tr(Rr.Root,{"data-slot":"separator",decorative:a,orientation:t,className:Sr("shrink-0 bg-border data-horizontal:h-px data-horizontal:w-full data-vertical:w-px data-vertical:self-stretch",e),...o})}import{cn as _e}from"cn";import{Dialog as ae}from"radix-ui";import{XIcon as Ir}from"lucide-react";import{jsx as $,jsxs as Mt}from"react/jsx-runtime";function Ta({...e}){return $(ae.Root,{"data-slot":"sheet",...e})}function zr({...e}){return $(ae.Portal,{"data-slot":"sheet-portal",...e})}function Dr({className:e,...t}){return $(ae.Overlay,{"data-slot":"sheet-overlay",className:_e("fixed inset-0 z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",e),...t})}function Ia({className:e,children:t,side:a="right",showCloseButton:o=!0,...r}){return Mt(zr,{children:[$(Dr,{}),Mt(ae.Content,{"data-slot":"sheet-content","data-side":a,className:_e("fixed z-50 flex flex-col gap-4 bg-popover bg-clip-padding text-sm text-popover-foreground shadow-lg transition duration-200 ease-in-out data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-[side=bottom]:data-open:slide-in-from-bottom-10 data-[side=left]:data-open:slide-in-from-left-10 data-[side=right]:data-open:slide-in-from-right-10 data-[side=top]:data-open:slide-in-from-top-10 data-closed:animate-out data-closed:fade-out-0 data-[side=bottom]:data-closed:slide-out-to-bottom-10 data-[side=left]:data-closed:slide-out-to-left-10 data-[side=right]:data-closed:slide-out-to-right-10 data-[side=top]:data-closed:slide-out-to-top-10",e),...r,children:[t,o&&$(ae.Close,{"data-slot":"sheet-close",asChild:!0,children:Mt(p,{variant:"ghost",className:"absolute top-3 right-3",size:"icon-sm",children:[$(Ir,{}),$("span",{className:"sr-only",children:"Close"})]})})]})]})}function za({className:e,...t}){return $("div",{"data-slot":"sheet-header",className:_e("flex flex-col gap-0.5 p-4",e),...t})}function Da({className:e,...t}){return $(ae.Title,{"data-slot":"sheet-title",className:_e("font-heading text-base font-medium text-foreground",e),...t})}function Aa({className:e,...t}){return $(ae.Description,{"data-slot":"sheet-description",className:_e("text-sm text-muted-foreground",e),...t})}import{cn as Ar}from"cn";import{jsx as Mr}from"react/jsx-runtime";function Ma({className:e,...t}){return Mr("div",{"data-slot":"skeleton",className:Ar("animate-pulse rounded-md bg-muted",e),...t})}import{cn as Br}from"cn";import{Tooltip as Ge}from"radix-ui";import{jsx as nt,jsxs as Lr}from"react/jsx-runtime";function Ba({...e}){return nt(Ge.Root,{"data-slot":"tooltip",...e})}function La({...e}){return nt(Ge.Trigger,{"data-slot":"tooltip-trigger",...e})}function Ea({className:e,sideOffset:t=0,children:a,...o}){return nt(Ge.Portal,{children:Lr(Ge.Content,{"data-slot":"tooltip-content",sideOffset:t,className:Br("z-50 inline-flex w-fit max-w-xs origin-(--radix-tooltip-content-transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",e),...o,children:[a,nt(Ge.Arrow,{className:"z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground"})]})})}import{PanelLeftIcon as _r}from"lucide-react";import{jsx as x,jsxs as Fe}from"react/jsx-runtime";var Gr="sidebar_state",Fr=3600*24*7,Or="16rem",Vr="18rem",$r="3rem",Hr="b",Ga=M.createContext(null);function xe(){let e=M.useContext(Ga);if(!e)throw new Error("useSidebar must be used within a SidebarProvider.");return e}function Fa({defaultOpen:e=!0,open:t,onOpenChange:a,className:o,style:r,children:i,...s}){let n=Sa(),[l,c]=M.useState(!1),[f,k]=M.useState(e),w=t??f,S=M.useCallback(g=>{let y=typeof g=="function"?g(w):g;a?a(y):k(y),document.cookie=`${Gr}=${y}; path=/; max-age=${Fr}`},[a,w]),C=M.useCallback(()=>n?c(g=>!g):S(g=>!g),[n,S,c]);M.useEffect(()=>{let g=y=>{y.key===Hr&&(y.metaKey||y.ctrlKey)&&(y.preventDefault(),C())};return window.addEventListener("keydown",g),()=>window.removeEventListener("keydown",g)},[C]);let v=w?"expanded":"collapsed",P=M.useMemo(()=>({state:v,open:w,setOpen:S,isMobile:n,openMobile:l,setOpenMobile:c,toggleSidebar:C}),[v,w,S,n,l,c,C]);return x(Ga.Provider,{value:P,children:x("div",{"data-slot":"sidebar-wrapper",style:{"--sidebar-width":Or,"--sidebar-width-icon":$r,...r},className:I("group/sidebar-wrapper flex min-h-svh w-full has-data-[variant=inset]:bg-sidebar",o),...s,children:i})})}function Oa({side:e="left",variant:t="sidebar",collapsible:a="offcanvas",className:o,children:r,dir:i,...s}){let{isMobile:n,state:l,openMobile:c,setOpenMobile:f}=xe();return a==="none"?x("div",{"data-slot":"sidebar",className:I("flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground",o),...s,children:r}):n?x(Ta,{open:c,onOpenChange:f,...s,children:Fe(Ia,{dir:i,"data-sidebar":"sidebar","data-slot":"sidebar","data-mobile":"true",className:"w-(--sidebar-width) bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden",style:{"--sidebar-width":Vr},side:e,children:[Fe(za,{className:"sr-only",children:[x(Da,{children:"Sidebar"}),x(Aa,{children:"Displays the mobile sidebar."})]}),x("div",{className:"flex h-full w-full flex-col",children:r})]})}):Fe("div",{className:"group peer hidden text-sidebar-foreground md:block","data-state":l,"data-collapsible":l==="collapsed"?a:"","data-variant":t,"data-side":e,"data-slot":"sidebar",children:[x("div",{"data-slot":"sidebar-gap",className:I("relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear","group-data-[collapsible=offcanvas]:w-0","group-data-[side=right]:rotate-180",t==="floating"||t==="inset"?"group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]":"group-data-[collapsible=icon]:w-(--sidebar-width-icon)")}),x("div",{"data-slot":"sidebar-container","data-side":e,className:I("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",t==="floating"||t==="inset"?"p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]":"group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l",o),...s,children:x("div",{"data-sidebar":"sidebar","data-slot":"sidebar-inner",className:"flex size-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1 group-data-[variant=floating]:ring-sidebar-border",children:r})})]})}function Va({className:e,onClick:t,...a}){let{toggleSidebar:o}=xe();return Fe(p,{"data-sidebar":"trigger","data-slot":"sidebar-trigger",variant:"ghost",size:"icon-sm",className:I(e),onClick:r=>{t?.(r),o()},...a,children:[x(_r,{}),x("span",{className:"sr-only",children:"Toggle Sidebar"})]})}function $a({className:e,...t}){let{toggleSidebar:a}=xe();return x("button",{"data-sidebar":"rail","data-slot":"sidebar-rail","aria-label":"Toggle Sidebar",tabIndex:-1,onClick:a,title:"Toggle Sidebar",className:I("absolute inset-y-0 z-20 hidden w-4 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:start-1/2 after:w-[2px] hover:after:bg-sidebar-border sm:flex ltr:-translate-x-1/2 rtl:-translate-x-1/2","in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize","[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize","group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full hover:group-data-[collapsible=offcanvas]:bg-sidebar","[[data-side=left][data-collapsible=offcanvas]_&]:-right-2","[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",e),...t})}function Ha({className:e,...t}){return x("main",{"data-slot":"sidebar-inset",className:I("relative flex w-full flex-1 flex-col 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",e),...t})}function Ka({className:e,...t}){return x("div",{"data-slot":"sidebar-header","data-sidebar":"header",className:I("flex flex-col gap-2 p-2",e),...t})}function Ua({className:e,...t}){return x("div",{"data-slot":"sidebar-content","data-sidebar":"content",className:I("no-scrollbar flex min-h-0 flex-1 flex-col gap-0 overflow-auto group-data-[collapsible=icon]:overflow-hidden",e),...t})}function Za({className:e,...t}){return x("div",{"data-slot":"sidebar-group","data-sidebar":"group",className:I("relative flex w-full min-w-0 flex-col p-2",e),...t})}function Bt({className:e,...t}){return x("ul",{"data-slot":"sidebar-menu","data-sidebar":"menu",className:I("flex w-full min-w-0 flex-col gap-0",e),...t})}function it({className:e,...t}){return x("li",{"data-slot":"sidebar-menu-item","data-sidebar":"menu-item",className:I("group/menu-item relative",e),...t})}var Kr=Er("peer/menu-button group/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm ring-sidebar-ring outline-hidden 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! hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:font-medium data-active:text-sidebar-accent-foreground [&_svg]:size-4 [&_svg]:shrink-0 [&>span:last-child]:truncate",{variants:{variant:{default:"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",outline:"bg-background shadow-[0_0_0_1px_var(--sidebar-border)] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_var(--sidebar-accent)]"},size:{default:"h-8 text-sm",sm:"h-7 text-xs",lg:"h-12 text-sm group-data-[collapsible=icon]:p-0!"}},defaultVariants:{variant:"default",size:"default"}});function st({asChild:e=!1,isActive:t=!1,variant:a="default",size:o="default",tooltip:r,className:i,...s}){let n=e?_a.Root:"button",{isMobile:l,state:c}=xe(),f=x(n,{"data-slot":"sidebar-menu-button","data-sidebar":"menu-button","data-size":o,"data-active":t,className:I(Kr({variant:a,size:o}),i),...s});return r?(typeof r=="string"&&(r={children:r}),Fe(Ba,{children:[x(La,{asChild:!0,children:f}),x(Ea,{side:"right",align:"center",hidden:c!=="collapsed"||l,...r})]})):f}function qa({className:e,...t}){return x("ul",{"data-slot":"sidebar-menu-sub","data-sidebar":"menu-sub",className:I("mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5 group-data-[collapsible=icon]:hidden",e),...t})}function Wa({className:e,...t}){return x("li",{"data-slot":"sidebar-menu-sub-item","data-sidebar":"menu-sub-item",className:I("group/menu-sub-item relative",e),...t})}function Xa({asChild:e=!1,size:t="md",isActive:a=!1,className:o,...r}){let i=e?_a.Root:"a";return x(i,{"data-slot":"sidebar-menu-sub-button","data-sidebar":"menu-sub-button","data-size":t,"data-active":a,className:I("flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground ring-sidebar-ring outline-hidden group-data-[collapsible=icon]:hidden hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[size=md]:text-sm data-[size=sm]:text-xs data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",o),...r})}import{jsx as b,jsxs as oe}from"react/jsx-runtime";function Et({nav:e,appName:t="LinkFox",appSubtitle:a,version:o}){let r=Ur(),i=Ee(e,r),{isMobile:s,setOpenMobile:n}=xe();return oe(Oa,{collapsible:"icon",children:[b(Ka,{children:b(Bt,{children:b(it,{children:b(st,{size:"lg",asChild:!0,children:oe(Lt,{href:"/",children:[b("div",{className:"flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary font-semibold text-sidebar-primary-foreground",children:"LF"}),oe("div",{className:"flex flex-col gap-0.5 leading-none",children:[oe("span",{className:"flex items-center gap-1.5 font-medium",children:[t,o?b("span",{className:"rounded border px-1 text-[10px] leading-4 font-normal text-muted-foreground tabular-nums",children:o}):null]}),a?b("span",{className:"text-xs text-muted-foreground",children:a}):null]})]})})})})}),b(Ua,{children:b(Za,{children:b(Bt,{children:e.map(l=>{if(l.items.length===1){let c=l.items[0];return b(it,{children:b(st,{tooltip:l.title,isActive:i?.group===l,asChild:!0,children:oe(Lt,{href:c.href,onClick:()=>s&&n(!1),children:[b(l.icon,{}),b("span",{children:l.title})]})})},l.title)}return b(ge,{asChild:!0,defaultOpen:!0,className:"group/collapsible",children:oe(it,{children:[b(be,{asChild:!0,children:oe(st,{tooltip:l.title,isActive:i?.group===l,children:[b(l.icon,{}),b("span",{children:l.title}),b(Zr,{className:"ml-auto transition-transform group-data-[state=open]/collapsible:rotate-90"})]})}),b(ve,{children:b(qa,{children:l.items.map(c=>b(Wa,{children:b(Xa,{asChild:!0,isActive:i?.item===c,children:b(Lt,{href:c.href,onClick:()=>s&&n(!1),children:b("span",{children:c.title})})})},c.href))})})]})},l.title)})})})}),b($a,{})]})}import{useEffect as Ft,useRef as Ot,useState as ne}from"react";import{BotIcon as nn,CheckCircle2Icon as sn,ChevronDownIcon as ln,ExternalLinkIcon as dn,FileTextIcon as cn,MessageCirclePlusIcon as Qa,SendIcon as pn,SparklesIcon as eo,SquareIcon as mn,TableIcon as un,Trash2Icon as fn,XCircleIcon as gn,XIcon as to}from"lucide-react";import qr from"react-markdown";import Wr from"remark-gfm";import{jsx as he}from"react/jsx-runtime";function _(e,t){function a({node:o,...r}){return he(e,{className:t,...r})}return a}var Xr={p:_("p","my-1.5 leading-relaxed"),ul:_("ul","my-1.5 list-disc pl-5"),ol:_("ol","my-1.5 list-decimal pl-5"),li:_("li","my-0.5"),h1:_("h3","mt-3 mb-1 font-semibold"),h2:_("h3","mt-3 mb-1 font-semibold"),h3:_("h4","mt-2 mb-1 font-semibold"),a:({href:e,children:t})=>he("a",{href:e,target:"_blank",rel:"noopener noreferrer",className:"break-all text-primary underline underline-offset-2",children:t}),code:_("code","rounded bg-muted px-1 py-0.5 font-mono text-xs"),pre:_("pre","my-2 overflow-x-auto rounded-md bg-muted p-2 text-xs [&_code]:bg-transparent [&_code]:p-0"),table:({children:e})=>he("div",{className:"my-2 overflow-x-auto rounded-md border",children:he("table",{className:"w-full text-xs",children:e})}),th:_("th","border-b bg-muted px-2 py-1 text-left font-medium whitespace-nowrap"),td:_("td","border-b px-2 py-1 align-top"),blockquote:_("blockquote","my-2 border-l-2 pl-3 text-muted-foreground")};function _t({children:e}){return he("div",{className:"text-sm break-words",children:he(qr,{remarkPlugins:[Wr],components:Xr,children:e})})}import{cn as re}from"cn";import{Select as L}from"radix-ui";import{ChevronDownIcon as Ja,CheckIcon as Jr,ChevronUpIcon as Yr}from"lucide-react";import{jsx as R,jsxs as Gt}from"react/jsx-runtime";function lt({...e}){return R(L.Root,{"data-slot":"select",...e})}function Ya({className:e,...t}){return R(L.Group,{"data-slot":"select-group",className:re("scroll-my-1 p-1",e),...t})}function dt({...e}){return R(L.Value,{"data-slot":"select-value",...e})}function ct({className:e,size:t="default",children:a,...o}){return Gt(L.Trigger,{"data-slot":"select-trigger","data-size":t,className:re("flex w-fit items-center justify-between gap-1.5 rounded-lg border border-input bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap transition-colors outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",e),...o,children:[a,R(L.Icon,{asChild:!0,children:R(Ja,{className:"pointer-events-none size-4 text-muted-foreground"})})]})}function pt({className:e,children:t,position:a="item-aligned",align:o="center",...r}){return R(L.Portal,{children:Gt(L.Content,{"data-slot":"select-content","data-align-trigger":a==="item-aligned",className:re("relative z-50 max-h-(--radix-select-content-available-height) min-w-36 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",a==="popper"&&"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",e),position:a,align:o,...r,children:[R(jr,{}),R(L.Viewport,{"data-position":a,className:re("data-[position=popper]:h-(--radix-select-trigger-height) data-[position=popper]:w-full data-[position=popper]:min-w-(--radix-select-trigger-width)",a==="popper"&&""),children:t}),R(Qr,{})]})})}function Oe({className:e,children:t,...a}){return Gt(L.Item,{"data-slot":"select-item",className:re("relative flex w-full cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",e),...a,children:[R("span",{className:"pointer-events-none absolute right-2 flex size-4 items-center justify-center",children:R(L.ItemIndicator,{children:R(Jr,{className:"pointer-events-none"})})}),R(L.ItemText,{children:t})]})}function jr({className:e,...t}){return R(L.ScrollUpButton,{"data-slot":"select-scroll-up-button",className:re("z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",e),...t,children:R(Yr,{})})}function Qr({className:e,...t}){return R(L.ScrollDownButton,{"data-slot":"select-scroll-down-button",className:re("z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",e),...t,children:R(Ja,{})})}import{cn as en}from"cn";import{Loader2Icon as tn}from"lucide-react";import{jsx as an}from"react/jsx-runtime";function Y({className:e,...t}){return an(tn,{"data-slot":"spinner",role:"status","aria-label":"Loading",className:en("size-4 animate-spin",e),...t})}import{cn as on}from"cn";import{jsx as rn}from"react/jsx-runtime";function ja({className:e,...t}){return rn("textarea",{"data-slot":"textarea",className:on("flex field-sizing-content min-h-16 w-full rounded-lg border border-input bg-transparent px-2.5 py-2 text-base transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",e),...t})}import{cn as bn}from"cn";import{Fragment as yn,jsx as d,jsxs as h}from"react/jsx-runtime";var vn=["介绍一下这个应用现在能做什么","帮我梳理接下来可以加哪些功能"],xn="例如:帮我把当前页面的数据按状态汇总一下",ao=e=>Tt.find(t=>t.id===e)?.name??e;function Vt({suggestions:e}){let{open:t,setOpen:a,page:o}=zt(),[r,i]=ne(),[s,n]=ne([]),[l,c]=ne(""),[f,k]=ne("default"),[w,S]=ne(!0),[C,v]=ne(""),P=Ot(null),g=Ot(null),y=Ot(null),q=s.some(m=>m.running),Pt=!!o&&(!!o.table||o.records.length>0),Qe=()=>v("");Ft(()=>{!t||r||va().getNotebook().then(m=>i({notebookId:m.notebookId,name:m.name})).catch(()=>{})},[t,r]);let kt=o?`${o.table?.id}:${o.records.map(m=>m.id).join(",")}`:"",[mr,ur]=ne(kt);kt!==mr&&(ur(kt),S(!0)),Ft(()=>{y.current?.scrollIntoView({block:"end"})},[s]),Ft(()=>()=>P.current?.abort(),[]);let et=(m,Le)=>n(tt=>tt.map(W=>W.id===m?{...W,...Le}:W)),aa=async(m=l)=>{let Le=m.trim();if(!Le||q)return;let tt=w&&Pt?o:null,W=crypto.randomUUID(),St=C;n(F=>[...F,{id:W,input:Le,context:tt,modelId:f,running:!0,followUp:!!St}]),c("");let Rt=new AbortController;P.current=Rt,g.current=null;try{let F=await ba(Na(Le,St?null:tt,r),f,{signal:Rt.signal,sessionId:St||void 0,onUpdate:at=>{g.current=at.messageId,at.sessionId&&v(at.sessionId),et(W,{task:at})}});F.sessionId&&v(F.sessionId),et(W,{task:F,running:!1,error:F.stopReason==="end_turn"?void 0:`任务异常结束(${F.stopReason})`}),window.dispatchEvent(new Event(ya));let oa=await ga(F.messageId);oa&&et(W,{shareUrl:oa})}catch(F){et(W,{running:!1,error:ra(F)?"已停止":na(F)})}finally{P.current===Rt&&(P.current=null)}},fr=()=>{let m=g.current;P.current?.abort(),m&&fa(m).catch(()=>{})},gr=e?.items??[],br=(o?gr.find(m=>o.source.endsWith(m.match))?.items:void 0)??e?.fallback??vn;return h("aside",{"aria-label":"LinkFox OS 助手",className:bn("z-40 flex flex-col border-l bg-background","fixed inset-0 md:sticky md:top-0 md:h-svh md:w-1/4 md:min-w-90 md:shrink-0 md:self-start",!t&&"hidden"),children:[h("header",{className:"flex h-14 shrink-0 items-center gap-2 border-b px-3",children:[d(eo,{className:"size-4 text-primary"}),d("span",{className:"font-medium",children:"LinkFox OS"}),h(lt,{value:f,onValueChange:m=>{k(m),Qe()},disabled:q,children:[d(ct,{size:"sm",className:"ml-auto w-32","aria-label":"选择 Agent",children:d(dt,{})}),d(pt,{align:"end",children:Tt.map(m=>d(Oe,{value:m.id,children:m.name},m.id))})]}),d(p,{variant:"ghost",size:"icon-sm","aria-label":"开新对话(不保留上下文)",title:"开新对话:下一条消息不再续接当前会话",disabled:q||!C,onClick:Qe,children:d(Qa,{})}),d(p,{variant:"ghost",size:"icon-sm","aria-label":"清空对话",disabled:q||!s.length,onClick:()=>{n([]),Qe()},children:d(fn,{})}),d(p,{variant:"ghost",size:"icon-sm","aria-label":"关闭助手",onClick:()=>a(!1),children:d(to,{})})]}),h("div",{className:"min-h-0 flex-1 overflow-y-auto overscroll-contain px-3 py-3",children:[s.length===0?h("div",{className:"flex flex-col gap-3 py-6 text-sm text-muted-foreground",children:[h("div",{className:"flex items-center gap-2 text-foreground",children:[d(nn,{className:"size-5"}),d("span",{className:"font-medium",children:"让 LinkFox 帮你干活"})]}),d("p",{children:"描述你要完成的事,LinkFox OS 会自己调用选品、数据查询、生图、多维表等技能去执行。勾选的记录会自动带上。"}),d("div",{className:"flex flex-col gap-2",children:br.map(m=>d("button",{type:"button",className:"rounded-lg border px-3 py-2 text-left text-foreground transition-colors hover:bg-muted",onClick:()=>c(m),children:m},m))})]}):d("div",{className:"flex flex-col gap-4",children:s.map(m=>d(Cn,{item:m,notebook:r},m.id))}),d("div",{ref:y})]}),h("div",{className:"shrink-0 border-t p-3",children:[C?h("div",{className:"mb-2 flex items-center gap-2 text-xs text-muted-foreground",children:[d(Qa,{className:"size-3.5 shrink-0"}),h("span",{className:"min-w-0 flex-1",children:["接着上一轮聊(",ao(f)," 记得前面的内容,可以直接追问)"]}),d("button",{type:"button",className:"shrink-0 text-primary underline-offset-2 hover:underline",onClick:Qe,children:"开新对话"})]}):h(yn,{children:[Pt&&w&&o&&d(hn,{context:o,notebook:r,onRemove:()=>S(!1)}),Pt&&!w&&d("button",{type:"button",className:"mb-2 text-xs text-primary underline-offset-2 hover:underline",onClick:()=>S(!0),children:"重新带入当前页面的数据表和勾选记录"})]}),h("div",{className:"flex items-end gap-2",children:[d(ja,{value:l,onChange:m=>c(m.target.value),onKeyDown:m=>{m.key==="Enter"&&!m.shiftKey&&!m.nativeEvent.isComposing&&(m.preventDefault(),aa())},placeholder:C?"接着问,例如:把第 3 条展开说说 / 换个角度再看一遍":e?.placeholder??xn,"aria-label":"告诉 LinkFox 要做什么",className:"max-h-40 min-h-16 resize-none"}),q?d(p,{size:"icon",variant:"outline","aria-label":"停止",onClick:fr,children:d(mn,{})}):d(p,{size:"icon","aria-label":"发送",disabled:!l.trim(),onClick:()=>aa(),children:d(pn,{})})]}),d("p",{className:"mt-2 text-xs text-muted-foreground",children:"执行会消耗 LinkFox 算力。Enter 发送,Shift+Enter 换行。"})]})]})}function hn({context:e,notebook:t,onRemove:a}){let o=e.records.length;return h(ge,{className:"mb-2 rounded-lg border bg-muted/40 text-xs",children:[h("div",{className:"flex items-center gap-2 px-2.5 py-2",children:[d(un,{className:"size-3.5 shrink-0 text-muted-foreground"}),h("div",{className:"min-w-0 flex-1",children:[e.table&&h("div",{className:"truncate",children:[t?`${t.name} / `:"",e.table.name]}),d("div",{className:"text-muted-foreground",children:o?`已勾选 ${o} 条记录,将一并发送`:`当前页面:${e.source}`})]}),o>0&&d(be,{asChild:!0,children:d(p,{variant:"ghost",size:"icon-xs","aria-label":"查看勾选记录",className:"[&[data-state=open]>svg]:rotate-180",children:d(ln,{})})}),d(p,{variant:"ghost",size:"icon-xs","aria-label":"不带入上下文",onClick:a,children:d(to,{})})]}),o>0&&d(ve,{children:d("ul",{className:"max-h-32 overflow-y-auto border-t px-2.5 py-1.5",children:e.records.map(r=>d("li",{className:"truncate py-0.5",title:r.label,children:r.label},r.id))})})]})}function Cn({item:e,notebook:t}){let{task:a,context:o}=e,r=a?.steps??[];return h("div",{className:"flex flex-col gap-2",children:[h("div",{className:"ml-6 self-end rounded-lg bg-primary px-3 py-2 text-sm whitespace-pre-wrap text-primary-foreground",children:[e.input,o&&h("div",{className:"mt-1.5 border-t border-primary-foreground/20 pt-1.5 text-xs opacity-80",children:[o.table?`${t?`${t.name} / `:""}${o.table.name}`:o.source,o.records.length?` · 勾选 ${o.records.length} 条`:""]})]}),h("div",{className:"mr-2 flex flex-col gap-2 rounded-lg border px-3 py-2",children:[h("div",{className:"flex items-center gap-1.5 text-xs text-muted-foreground",children:[d("span",{children:ao(e.modelId)}),e.followUp&&d("span",{className:"rounded bg-muted px-1.5 py-0.5",children:"接上一轮"})]}),r.length>0&&d("ul",{className:"flex flex-col gap-1 text-xs",children:r.map(i=>h("li",{className:"flex items-center gap-1.5",children:[i.status==="running"?d(Y,{className:"size-3"}):i.status==="failed"?d(gn,{className:"size-3 text-destructive"}):d(sn,{className:"size-3 text-emerald-600"}),d("span",{className:"truncate",children:i.status==="running"?`正在调用 ${i.title}`:i.title})]},i.id))}),a?.text?d(_t,{children:a.text}):e.running&&h("div",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:[d(Y,{})," ",a?"LinkFox 正在处理…":"正在提交任务…"]}),a&&a.files.length>0&&d("ul",{className:"flex flex-col gap-1",children:a.files.map(i=>d("li",{children:h("a",{href:i.uri,target:"_blank",rel:"noopener noreferrer",className:"flex items-center gap-1.5 text-xs text-primary underline-offset-2 hover:underline",children:[d(cn,{className:"size-3.5 shrink-0"}),d("span",{className:"truncate",children:i.name})]})},i.uri))}),e.error&&d("div",{className:"text-sm text-destructive",children:e.error}),e.shareUrl&&h("a",{href:e.shareUrl,target:"_blank",rel:"noopener noreferrer",className:"flex items-center gap-1 self-start text-xs text-muted-foreground underline-offset-2 hover:text-foreground hover:underline",children:["查看完整过程 ",d(dn,{className:"size-3"})]})]})]})}function $t(){let{open:e,setOpen:t}=zt();return h(p,{variant:e?"secondary":"default",size:"sm",onClick:()=>t(a=>!a),"aria-expanded":e,"aria-label":"让LinkFox帮你干活",children:[d(eo,{}),d("span",{className:"hidden sm:inline",children:"让LinkFox帮你干活"})]})}import{useMemo as Rn,useState as Tn}from"react";import{CheckIcon as go,GlobeIcon as In}from"lucide-react";import{Command as we}from"cmdk";import{cn as Ne}from"cn";import{cva as oo}from"class-variance-authority";import{cn as Ve}from"cn";import{jsx as $e}from"react/jsx-runtime";function Ce({className:e,...t}){return $e("div",{"data-slot":"input-group",role:"group",className:Ve("group/input-group relative flex h-8 w-full min-w-0 items-center rounded-lg border border-input transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:bg-input/50 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:bg-input/30 dark:has-disabled:bg-input/80 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5",e),...t})}var wn=oo("flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4",{variants:{align:{"inline-start":"order-first pl-2 has-[>button]:ml-[-0.3rem] has-[>kbd]:ml-[-0.15rem]","inline-end":"order-last pr-2 has-[>button]:mr-[-0.3rem] has-[>kbd]:mr-[-0.15rem]","block-start":"order-first w-full justify-start px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2","block-end":"order-last w-full justify-start px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2"}},defaultVariants:{align:"inline-start"}});function ye({className:e,align:t="inline-start",...a}){return $e("div",{role:"group","data-slot":"input-group-addon","data-align":t,className:Ve(wn({align:t}),e),onClick:o=>{o.target.closest("button")||o.currentTarget.parentElement?.querySelector("input")?.focus()},...a})}var Nn=oo("flex items-center gap-2 text-sm shadow-none",{variants:{size:{xs:"h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5",sm:"","icon-xs":"size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>svg]:p-0","icon-sm":"size-8 p-0 has-[>svg]:p-0"}},defaultVariants:{size:"xs"}});function ro({className:e,type:t="button",variant:a="ghost",size:o="xs",...r}){return $e(p,{type:t,"data-size":o,variant:a,className:Ve(Nn({size:o}),e),...r})}function no({className:e,...t}){return $e("span",{className:Ve("flex items-center gap-2 text-sm text-muted-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",e),...t})}function mt({className:e,...t}){return $e(te,{"data-slot":"input-group-control",className:Ve("flex-1 rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent",e),...t})}import{SearchIcon as Pn,CheckIcon as kn}from"lucide-react";import{jsx as X,jsxs as po}from"react/jsx-runtime";function io({className:e,...t}){return X(we,{"data-slot":"command",className:Ne("flex size-full flex-col overflow-hidden rounded-xl! bg-popover p-1 text-popover-foreground",e),...t})}function so({className:e,...t}){return X("div",{"data-slot":"command-input-wrapper",className:"p-1 pb-0",children:po(Ce,{className:"h-8! rounded-lg! border-input/30 bg-input/30 shadow-none! *:data-[slot=input-group-addon]:pl-2!",children:[X(we.Input,{"data-slot":"command-input",className:Ne("w-full text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",e),...t}),X(ye,{children:X(Pn,{className:"size-4 shrink-0 opacity-50"})})]})})}function lo({className:e,...t}){return X(we.List,{"data-slot":"command-list",className:Ne("no-scrollbar max-h-72 scroll-py-1 overflow-x-hidden overflow-y-auto outline-none",e),...t})}function co({className:e,...t}){return X(we.Empty,{"data-slot":"command-empty",className:Ne("py-6 text-center text-sm",e),...t})}function ut({className:e,...t}){return X(we.Group,{"data-slot":"command-group",className:Ne("overflow-hidden p-1 text-foreground **:[[cmdk-group-heading]]:px-2 **:[[cmdk-group-heading]]:py-1.5 **:[[cmdk-group-heading]]:text-xs **:[[cmdk-group-heading]]:font-medium **:[[cmdk-group-heading]]:text-muted-foreground",e),...t})}function Ht({className:e,children:t,...a}){return po(we.Item,{"data-slot":"command-item",className:Ne("group/command-item relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none in-data-[slot=dialog-content]:rounded-lg! data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-selected:bg-muted data-selected:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-selected:*:[svg]:text-foreground",e),...a,children:[t,X(kn,{className:"ml-auto opacity-0 group-has-data-[slot=command-shortcut]/command-item:hidden group-data-[checked=true]/command-item:opacity-100"})]})}import{cn as Sn}from"cn";import{Popover as ft}from"radix-ui";import{jsx as gt}from"react/jsx-runtime";function mo({...e}){return gt(ft.Root,{"data-slot":"popover",...e})}function uo({...e}){return gt(ft.Trigger,{"data-slot":"popover-trigger",...e})}function fo({className:e,align:t="center",sideOffset:a=4,...o}){return gt(ft.Portal,{children:gt(ft.Content,{"data-slot":"popover-content",align:t,sideOffset:a,className:Sn("z-50 flex w-72 origin-(--radix-popover-content-transform-origin) flex-col gap-2.5 rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",e),...o})})}import{cn as bo}from"cn";import{jsx as B,jsxs as ie}from"react/jsx-runtime";var Kt=["Asia/Shanghai","America/Los_Angeles","America/New_York","Europe/London","Europe/Berlin","Asia/Tokyo","UTC"];function zn(){try{return Intl.supportedValuesOf("timeZone")}catch{return Kt}}function Ut(){let[e,t]=Tn(!1),a=ha(),o=Ca(),r=Rn(()=>e?zn().filter(n=>!Kt.includes(n)).map(n=>({zone:n,offset:ot(n)})):[],[e]),i=n=>{xa(n),t(!1)},s=(n,l=ot(n))=>ie(Ht,{value:`${n} ${l}`,onSelect:()=>i(n),children:[B(go,{className:bo(!o&&n===a?"opacity-100":"opacity-0")}),B("span",{className:"truncate",children:n}),B("span",{className:"ml-auto text-xs text-muted-foreground",children:l})]},n);return ie(mo,{open:e,onOpenChange:t,children:[B(uo,{asChild:!0,children:ie(p,{variant:"outline",size:"sm","aria-label":"选择时区",children:[B(In,{"data-icon":"inline-start"}),B("span",{className:"hidden max-w-40 truncate sm:inline",children:a}),B("span",{className:"text-muted-foreground",children:ot(a)})]})}),B(fo,{align:"end",className:"w-80 p-0",children:ie(io,{children:[B(so,{placeholder:"搜索时区,如 Shanghai、UTC+08"}),ie(lo,{children:[B(co,{children:"没有匹配的时区"}),B(ut,{heading:"默认",children:ie(Ht,{value:`跟随浏览器 ${It()}`,onSelect:()=>i(null),children:[B(go,{className:bo(o?"opacity-100":"opacity-0")}),ie("span",{className:"truncate",children:["跟随浏览器(",It(),")"]})]})}),B(ut,{heading:"常用",children:Kt.map(n=>s(n))}),B(ut,{heading:"全部",children:r.map(n=>s(n.zone,n.offset))})]})]})})]})}import{LogOutIcon as Mn,UserIcon as Bn}from"lucide-react";import{cn as He}from"cn";import{DropdownMenu as H}from"radix-ui";import{CheckIcon as Dn,ChevronRightIcon as Wl}from"lucide-react";import{jsx as O,jsxs as An}from"react/jsx-runtime";function Pe({...e}){return O(H.Root,{"data-slot":"dropdown-menu",...e})}function ke({...e}){return O(H.Trigger,{"data-slot":"dropdown-menu-trigger",...e})}function Se({className:e,align:t="start",sideOffset:a=4,...o}){return O(H.Portal,{children:O(H.Content,{"data-slot":"dropdown-menu-content",sideOffset:a,align:t,className:He("z-50 max-h-(--radix-dropdown-menu-content-available-height) w-(--radix-dropdown-menu-trigger-width) min-w-32 origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:overflow-hidden data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",e),...o})})}function Ke({...e}){return O(H.Group,{"data-slot":"dropdown-menu-group",...e})}function se({className:e,inset:t,variant:a="default",...o}){return O(H.Item,{"data-slot":"dropdown-menu-item","data-inset":t,"data-variant":a,className:He("group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive",e),...o})}function vo({className:e,children:t,checked:a,inset:o,...r}){return An(H.CheckboxItem,{"data-slot":"dropdown-menu-checkbox-item","data-inset":o,className:He("relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",e),checked:a,...r,children:[O("span",{className:"pointer-events-none absolute right-2 flex items-center justify-center","data-slot":"dropdown-menu-checkbox-item-indicator",children:O(H.ItemIndicator,{children:O(Dn,{})})}),t]})}function Ue({className:e,inset:t,...a}){return O(H.Label,{"data-slot":"dropdown-menu-label","data-inset":t,className:He("px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7",e),...a})}function bt({className:e,...t}){return O(H.Separator,{"data-slot":"dropdown-menu-separator",className:He("-mx-1 my-1 h-px bg-border",e),...t})}import{Fragment as Ln,jsx as Re,jsxs as Ze}from"react/jsx-runtime";function Zt(){let e=rt();return e.status!=="ready"?null:Ze(Pe,{children:[Re(ke,{asChild:!0,children:Re(p,{variant:"ghost",size:"icon","aria-label":"账号",children:Re(Bn,{})})}),Ze(Se,{align:"end",children:[Re(Ue,{children:e.userName||"LinkFox 用户"}),e.apiKey&&Ze(Ue,{className:"font-normal text-muted-foreground",children:["API Key:",ua(e.apiKey)]}),!e.apiKey&&Ze(Ln,{children:[Re(bt,{}),Ze(se,{onSelect:ma,children:[Re(Mn,{}),"退出登录"]})]})]})]})}import{cn as Te}from"cn";import{Slot as En}from"radix-ui";import{ChevronRightIcon as _n,MoreHorizontalIcon as id}from"lucide-react";import{jsx as le,jsxs as ld}from"react/jsx-runtime";function xo({className:e,...t}){return le("nav",{"aria-label":"breadcrumb","data-slot":"breadcrumb",className:Te(e),...t})}function ho({className:e,...t}){return le("ol",{"data-slot":"breadcrumb-list",className:Te("flex flex-wrap items-center gap-1.5 text-sm wrap-break-word text-muted-foreground",e),...t})}function qt({className:e,...t}){return le("li",{"data-slot":"breadcrumb-item",className:Te("inline-flex items-center gap-1",e),...t})}function Co({asChild:e,className:t,...a}){let o=e?En.Root:"a";return le(o,{"data-slot":"breadcrumb-link",className:Te("transition-colors hover:text-foreground",t),...a})}function yo({className:e,...t}){return le("span",{"data-slot":"breadcrumb-page",role:"link","aria-disabled":"true","aria-current":"page",className:Te("font-normal text-foreground",e),...t})}function wo({children:e,className:t,...a}){return le("li",{"data-slot":"breadcrumb-separator",role:"presentation","aria-hidden":"true",className:Te("[&>svg]:size-3.5",t),...a,children:e??le(_n,{})})}import{jsx as T,jsxs as qe}from"react/jsx-runtime";function Vn({children:e,nav:t,appName:a,appSubtitle:o,version:r,suggestions:i}){let s=On(),n=Ee(t,s),l=n?[...new Set([n.group.title,n.item.title])]:[];return T(wa,{children:qe(Fa,{children:[T(Et,{nav:t,appName:a,appSubtitle:o,version:r}),qe(Ha,{className:"min-w-0",children:[qe("header",{className:"sticky top-0 z-10 flex h-14 shrink-0 items-center gap-2 border-b bg-background px-4",children:[T(Va,{className:"-ml-1"}),T(Ra,{orientation:"vertical",className:"mr-2 data-[orientation=vertical]:h-4"}),T(xo,{className:"min-w-0 flex-1",children:qe(ho,{children:[T(qt,{className:"hidden md:inline-flex",children:T(Co,{asChild:!0,children:T(Fn,{href:"/",children:"首页"})})}),l.map((c,f)=>qe(Gn,{children:[T(wo,{className:f===0?"hidden md:block":void 0}),T(qt,{className:f<l.length-1?"hidden md:inline-flex":void 0,children:f===l.length-1?T(yo,{children:c}):T("span",{children:c})})]},c))]})}),T($t,{}),T(Ut,{}),T(Zt,{})]}),T("main",{className:"flex min-w-0 flex-1 flex-col gap-4 p-4",children:e})]}),T(Vt,{suggestions:i})]})})}import{useEffect as Kn}from"react";import{CircleAlertIcon as Un,LogInIcon as Io,RotateCwIcon as Zn}from"lucide-react";import{cva as $n}from"class-variance-authority";import{cn as Ie}from"cn";import{jsx as ze}from"react/jsx-runtime";function No({className:e,...t}){return ze("div",{"data-slot":"empty",className:Ie("flex w-full min-w-0 flex-1 flex-col items-center justify-center gap-4 rounded-xl border-dashed p-6 text-center text-balance",e),...t})}function Po({className:e,...t}){return ze("div",{"data-slot":"empty-header",className:Ie("flex max-w-sm flex-col items-center gap-2",e),...t})}var Hn=$n("mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0",{variants:{variant:{default:"bg-transparent",icon:"flex size-8 shrink-0 items-center justify-center rounded-lg bg-muted text-foreground [&_svg:not([class*='size-'])]:size-4"}},defaultVariants:{variant:"default"}});function ko({className:e,variant:t="default",...a}){return ze("div",{"data-slot":"empty-icon","data-variant":t,className:Ie(Hn({variant:t,className:e})),...a})}function So({className:e,...t}){return ze("div",{"data-slot":"empty-title",className:Ie("font-heading text-sm font-medium tracking-tight",e),...t})}function Ro({className:e,...t}){return ze("div",{"data-slot":"empty-description",className:Ie("text-sm/relaxed text-muted-foreground [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",e),...t})}function To({className:e,...t}){return ze("div",{"data-slot":"empty-content",className:Ie("flex w-full max-w-sm min-w-0 flex-col items-center gap-2.5 text-sm text-balance",e),...t})}import{jsx as G,jsxs as vt}from"react/jsx-runtime";function qn({children:e}){let t=rt();if(Kn(()=>{da()},[]),t.status==="ready")return e;if(t.status==="loading"||t.status==="callback")return vt("div",{className:"flex min-h-svh items-center justify-center gap-2",role:"status",children:[G(Y,{}),G("span",{children:t.status==="callback"?"正在完成登录…":"正在准备登录…"})]});let a=t.status==="error",o=t.status==="redirecting";return G("div",{className:"flex min-h-svh items-center justify-center bg-muted p-4",children:vt(No,{className:"max-w-md bg-background",children:[vt(Po,{children:[G(ko,{variant:"icon",children:a?G(Un,{}):G(Io,{})}),G(So,{children:a?"无法进入选品工作台":"登录 LinkFox"}),G(Ro,{children:a?t.message:"使用 LinkFox 账号登录,登录状态将在此浏览器中保留至到期或退出。"})]}),G(To,{children:vt(p,{disabled:o,onClick:a&&t.action==="config"?()=>{ca()}:()=>{pa()},children:[o?G(Y,{"data-icon":"inline-start"}):a?G(Zn,{"data-icon":"inline-start"}):G(Io,{"data-icon":"inline-start"}),o?"正在跳转…":a?"重试":"登录 LinkFox"]})})]})})}import*as zo from"react";import{ThemeProvider as Wn,useTheme as Xn}from"next-themes";import{jsx as Qn,jsxs as ei}from"react/jsx-runtime";function Jn({children:e,...t}){return ei(Wn,{attribute:"class",defaultTheme:"system",enableSystem:!0,disableTransitionOnChange:!0,...t,children:[Qn(jn,{}),e]})}function Yn(e){return e instanceof HTMLElement?e.isContentEditable||e.tagName==="INPUT"||e.tagName==="TEXTAREA"||e.tagName==="SELECT":!1}function jn(){let{resolvedTheme:e,setTheme:t}=Xn();return zo.useEffect(()=>{function a(o){o.defaultPrevented||o.repeat||o.metaKey||o.ctrlKey||o.altKey||o.key.toLowerCase()==="d"&&(Yn(o.target)||t(e==="dark"?"light":"dark"))}return window.addEventListener("keydown",a),()=>{window.removeEventListener("keydown",a)}},[e,t]),null}import{cn as ti}from"cn";import{Checkbox as Do}from"radix-ui";import{CheckIcon as ai}from"lucide-react";import{jsx as Wt}from"react/jsx-runtime";function de({className:e,...t}){return Wt(Do.Root,{"data-slot":"checkbox",className:ti("peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input transition-colors outline-none group-has-disabled/field:opacity-50 group-has-[:focus-visible]/field-label:ring-0 group-has-[:focus-visible]/field-label:not-data-checked:border-input after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground group-has-[:focus-visible]/field-label:data-checked:border-primary dark:data-checked:bg-primary",e),...t,children:Wt(Do.Indicator,{"data-slot":"checkbox-indicator",className:"grid place-content-center text-current transition-none [&>svg]:size-3.5",children:Wt(ai,{})})})}import{cn as De}from"cn";import{jsx as ce}from"react/jsx-runtime";function Ao({className:e,...t}){return ce("div",{"data-slot":"table-container",className:"relative w-full overflow-x-auto",children:ce("table",{"data-slot":"table",className:De("w-full caption-bottom text-sm",e),...t})})}function Mo({className:e,...t}){return ce("thead",{"data-slot":"table-header",className:De("[&_tr]:border-b",e),...t})}function Bo({className:e,...t}){return ce("tbody",{"data-slot":"table-body",className:De("[&_tr:last-child]:border-0",e),...t})}function We({className:e,...t}){return ce("tr",{"data-slot":"table-row",className:De("border-b transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-[state=selected]:bg-muted",e),...t})}function xt({className:e,...t}){return ce("th",{"data-slot":"table-head",className:De("h-10 px-2 text-left align-middle font-medium text-foreground [&:has([role=checkbox])]:pr-0",e),...t})}function Ae({className:e,...t}){return ce("td",{"data-slot":"table-cell",className:De("p-2 align-middle break-words [&:has([role=checkbox])]:pr-0",e),...t})}import{cn as ht}from"cn";import{jsx as z,jsxs as Ct}from"react/jsx-runtime";var Lo=56,Eo=120;function oi({columns:e,rows:t,rowKey:a,renderCell:o,actions:r,actionsWidth:i=200,selection:s,onRowClick:n,loading:l,skeletonRows:c=8,empty:f,className:k}){let w=e.length+(s?1:0)+(r?1:0),C={"--dt-min-width":`${e.reduce((v,P)=>v+(P.width??Eo),0)+(s?Lo:0)+(r?i:0)}px`};return Ct(Ao,{style:C,className:ht("lg:[min-width:var(--dt-min-width)] max-lg:block",k),children:[z(Mo,{className:"max-lg:hidden",children:Ct(We,{children:[s&&z(xt,{style:{width:Lo},className:"lg:sticky lg:left-0 lg:z-20 lg:bg-card",children:z(de,{"aria-label":"全选本页",checked:s.pageAllSelected?!0:s.pageSomeSelected?"indeterminate":!1,disabled:!t.length,onCheckedChange:v=>s.onToggleAll(v===!0)})}),e.map(v=>z(xt,{style:{width:v.width??Eo},className:"break-words",children:v.label},v.key)),r&&z(xt,{style:{width:i},className:"text-right lg:sticky lg:right-0 lg:z-20 lg:border-l lg:bg-card",children:"操作"})]})}),Ct(Bo,{className:"max-lg:block",children:[l&&t.length===0?Array.from({length:c},(v,P)=>z(We,{className:"max-lg:block max-lg:border-0",children:z(Ae,{colSpan:w,className:"max-lg:block",children:z(Ma,{className:"h-10 w-full"})})},P)):t.map(v=>{let P=a(v);return Ct(We,{"data-state":s?.selected.has(P)?"selected":void 0,onClick:n?()=>n(v):void 0,className:ht("group/row",l&&"opacity-60",n&&"cursor-pointer","max-lg:mb-3 max-lg:block max-lg:rounded-lg max-lg:border max-lg:p-3"),children:[s&&z(Ae,{className:"max-lg:flex max-lg:items-center max-lg:border-0 max-lg:px-0 max-lg:py-1 lg:sticky lg:left-0 lg:z-10 lg:bg-card lg:group-hover/row:bg-muted",children:z(de,{"aria-label":"选择本行",checked:s.selected.has(P),onCheckedChange:g=>s.onToggleRow(v,g===!0),onClick:g=>g.stopPropagation()})}),e.map(g=>z(Ae,{"data-label":g.label,className:ht("align-top break-words","max-lg:flex max-lg:gap-3 max-lg:border-0 max-lg:px-0 max-lg:py-1","max-lg:before:w-24 max-lg:before:shrink-0 max-lg:before:text-xs max-lg:before:text-muted-foreground","max-lg:before:content-[attr(data-label)]"),children:z("div",{className:"min-w-0 flex-1",children:o(v,g)})},g.key)),r&&z(Ae,{className:ht("align-top text-right max-lg:flex max-lg:justify-end max-lg:border-0 max-lg:px-0 max-lg:py-1","lg:sticky lg:right-0 lg:z-10 lg:border-l lg:bg-card lg:group-hover/row:bg-muted"),children:z("div",{className:"flex justify-end gap-1",onClick:g=>g.stopPropagation(),children:r(v)})})]},P)}),!l&&t.length===0&&f?z(We,{className:"max-lg:block max-lg:border-0 hover:bg-transparent",children:z(Ae,{colSpan:w,className:"whitespace-normal max-lg:block",children:f})}):null]})]})}import{cn as Me}from"cn";import{ChevronLeftIcon as ri,ChevronRightIcon as ni,MoreHorizontalIcon as ii}from"lucide-react";import{jsx as V,jsxs as Xt}from"react/jsx-runtime";function _o({className:e,...t}){return V("nav",{role:"navigation","aria-label":"pagination","data-slot":"pagination",className:Me("mx-auto flex w-full justify-center",e),...t})}function Go({className:e,...t}){return V("ul",{"data-slot":"pagination-content",className:Me("flex items-center gap-0.5",e),...t})}function Xe({...e}){return V("li",{"data-slot":"pagination-item",...e})}function yt({className:e,isActive:t,size:a="icon",...o}){return V(p,{asChild:!0,variant:t?"outline":"ghost",size:a,className:Me(e),children:V("a",{"aria-current":t?"page":void 0,"data-slot":"pagination-link","data-active":t,...o})})}function Fo({className:e,text:t="Previous",...a}){return Xt(yt,{"aria-label":"Go to previous page",size:"default",className:Me("pl-1.5!",e),...a,children:[V(ri,{"data-icon":"inline-start"}),V("span",{className:"hidden sm:block",children:t})]})}function Oo({className:e,text:t="Next",...a}){return Xt(yt,{"aria-label":"Go to next page",size:"default",className:Me("pr-1.5!",e),...a,children:[V("span",{className:"hidden sm:block",children:t}),V(ni,{"data-icon":"inline-end"})]})}function Vo({className:e,...t}){return Xt("span",{"aria-hidden":!0,"data-slot":"pagination-ellipsis",className:Me("flex size-8 items-center justify-center [&_svg:not([class*='size-'])]:size-4",e),...t,children:[V(ii,{}),V("span",{className:"sr-only",children:"More pages"})]})}import{cn as $o}from"cn";import{jsx as K,jsxs as Jt}from"react/jsx-runtime";var Ho=20;function si(e,t){if(t<=7)return Array.from({length:t},(i,s)=>s+1);let a=[1],o=Math.max(2,e-1),r=Math.min(t-1,e+1);o>2&&a.push("…");for(let i=o;i<=r;i++)a.push(i);return r<t-1&&a.push("…"),a.push(t),a}function li({page:e,total:t,disabled:a,onChange:o,pageSize:r=Ho,note:i}){let s=Math.max(1,Math.ceil(t/r)),n=c=>f=>{f.preventDefault(),!(a||c<1||c>s||c===e)&&o(c)},l=c=>$o(c&&"pointer-events-none opacity-50");return Jt("div",{className:"flex flex-col items-center justify-between gap-2 sm:flex-row",children:[Jt("p",{className:"text-sm text-muted-foreground",children:["共 ",t.toLocaleString("zh-CN")," 条,第 ",e,"/",s," 页,每页 ",r," 条",i?K("span",{className:"ml-2",children:i}):null]}),K(_o,{className:"mx-0 w-auto",children:Jt(Go,{children:[K(Xe,{children:K(Fo,{href:"#",text:"上一页","aria-label":"上一页",onClick:n(e-1),className:l(a||e<=1)})}),si(e,s).map((c,f)=>c==="…"?K(Xe,{className:"hidden sm:block",children:K(Vo,{})},`e${f}`):K(Xe,{className:$o(c!==e&&"hidden sm:block"),children:K(yt,{href:"#",isActive:c===e,onClick:n(c),className:l(!!a),children:c})},c)),K(Xe,{children:K(Oo,{href:"#",text:"下一页","aria-label":"下一页",onClick:n(e+1),className:l(a||e>=s)})})]})})]})}import{useState as gi}from"react";import{ChevronDownIcon as bi,RotateCcwIcon as vi,SearchIcon as xi}from"lucide-react";import{ChevronDownIcon as di}from"lucide-react";import{jsx as j,jsxs as Ko}from"react/jsx-runtime";function Yt({id:e,value:t,onChange:a,options:o,placeholder:r,multiple:i}){let s=n=>{if(!i)return a(n);let l=t.split(/[,,、]/).map(c=>c.trim()).filter(Boolean);a(l.includes(n)?l.join(","):[...l,n].join(","))};return Ko(Ce,{children:[j(mt,{id:e,value:t,placeholder:r??"请选择或输入",onChange:n=>a(n.target.value)}),j(ye,{align:"inline-end",children:Ko(Pe,{children:[j(ke,{asChild:!0,children:j(ro,{size:"icon-xs","aria-label":"展开选项",children:j(di,{})})}),j(Se,{align:"end",className:"max-h-72 overflow-y-auto",children:j(Ke,{children:o.map(n=>j(se,{onSelect:()=>s(n.value),children:n.label??n.value},n.value))})})]})})]})}import{cn as Uo}from"cn";import{jsx as Wo}from"react/jsx-runtime";function Zo({className:e,size:t="default",...a}){return Wo("div",{"data-slot":"card","data-size":t,className:Uo("group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",e),...a})}function qo({className:e,...t}){return Wo("div",{"data-slot":"card-content",className:Uo("px-(--card-spacing)",e),...t})}import{useMemo as yc}from"react";import{cva as ui}from"class-variance-authority";import{cn as jt}from"cn";import{cn as ci}from"cn";import{Label as pi}from"radix-ui";import{jsx as mi}from"react/jsx-runtime";function Be({className:e,...t}){return mi(pi.Root,{"data-slot":"label",className:ci("flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",e),...t})}import{jsx as ea,jsxs as Sc}from"react/jsx-runtime";function Qt({className:e,...t}){return ea("div",{"data-slot":"field-group",className:jt("group/field-group @container/field-group flex w-full flex-col gap-5 data-[slot=checkbox-group]:gap-3 *:data-[slot=field-group]:gap-4",e),...t})}var fi=ui("group/field flex w-full gap-2 data-[invalid=true]:text-destructive",{variants:{orientation:{vertical:"flex-col *:w-full [&>.sr-only]:w-auto",horizontal:"flex-row items-center has-[>[data-slot=field-content]]:items-start *:data-[slot=field-label]:flex-auto has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",responsive:"flex-col *:w-full @md/field-group:flex-row @md/field-group:items-center @md/field-group:*:w-auto @md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:*:data-[slot=field-label]:flex-auto [&>.sr-only]:w-auto @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px"}},defaultVariants:{orientation:"vertical"}});function pe({className:e,orientation:t="vertical",...a}){return ea("div",{role:"group","data-slot":"field","data-orientation":t,className:jt(fi({orientation:t}),e),...a})}function me({className:e,...t}){return ea(Be,{"data-slot":"field-label",className:jt("group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50 has-data-checked:border-primary/30 has-data-checked:bg-primary/5 has-[>[data-slot=field]]:rounded-lg has-[>[data-slot=field]]:border has-[>[data-slot=field]]:not-has-[:disabled,[data-disabled]]:hover:bg-muted/50 has-[>[data-slot=field]]:has-[:focus-visible]:border-ring has-[>[data-slot=field]]:has-[:focus-visible]:ring-3 has-[>[data-slot=field]]:has-[:focus-visible]:ring-ring/50 *:data-[slot=field]:p-2.5 dark:has-data-checked:border-primary/20 dark:has-data-checked:bg-primary/10","has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col",e),...t})}import{cn as Xo}from"cn";import{jsx as u,jsxs as N}from"react/jsx-runtime";var Jo="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4";function Yo({spec:e,values:t,set:a,currency:o}){let r=`ff-${e.id}`;switch(e.type){case"range":{let i=e.price?o:e.unit,s=(n,l,c)=>N(Ce,{children:[u(mt,{id:n.endsWith("gte")?r:void 0,inputMode:"decimal","aria-label":`${e.label}${c}`,placeholder:l,value:t[n]??"",onChange:f=>a(n,f.target.value)}),i&&u(ye,{align:"inline-end",children:u(no,{children:i})})]});return N(pe,{children:[u(me,{htmlFor:r,children:e.label}),N("div",{className:"flex items-center gap-2",children:[s(`${e.id}.gte`,"最小","最小值"),u("span",{className:"text-muted-foreground",children:"至"}),s(`${e.id}.lte`,"最大","最大值")]})]})}case"dateRange":return N(pe,{children:[u(me,{htmlFor:r,children:e.label}),N("div",{className:"flex items-center gap-2",children:[u(te,{id:r,type:"date","aria-label":`${e.label}开始`,value:t[`${e.id}.gte`]??"",onChange:i=>a(`${e.id}.gte`,i.target.value)}),u("span",{className:"text-muted-foreground",children:"至"}),u(te,{type:"date","aria-label":`${e.label}结束`,value:t[`${e.id}.lte`]??"",onChange:i=>a(`${e.id}.lte`,i.target.value)})]})]});case"text":return N(pe,{children:[u(me,{htmlFor:r,children:e.label}),u(te,{id:r,placeholder:e.placeholder,value:t[e.id]??"",onChange:i=>a(e.id,i.target.value)})]});case"list":return N(pe,{children:[u(me,{htmlFor:r,children:e.label}),e.options?u(Yt,{id:r,placeholder:e.placeholder,value:t[e.id]??"",options:e.options.map(i=>({value:i})),multiple:e.multiple,onChange:i=>a(e.id,i)}):u(te,{id:r,placeholder:e.placeholder,value:t[e.id]??"",onChange:i=>a(e.id,i.target.value)})]});case"flags":{let i=sa(t[e.id]);return N(pe,{children:[u(me,{children:e.label}),u("div",{className:"flex flex-wrap gap-x-4 gap-y-2 pt-1",children:e.options.map(s=>N(Be,{className:"flex items-center gap-2 font-normal",children:[u(de,{checked:i.includes(s.value),onCheckedChange:n=>a(e.id,la(t[e.id],s.value,n===!0))}),s.label]},s.value))})]})}case"bool":case"select":{let i=e.type==="bool"?[{value:"yes",label:"是"},{value:"no",label:"否"}]:e.options,s=e.type==="select"&&e.required,n=s?t[e.id]||i[0]?.value:t[e.id]||"any";return N(pe,{children:[u(me,{htmlFor:r,children:e.label}),N(lt,{value:n,onValueChange:l=>a(e.id,l==="any"?"":l),children:[u(ct,{id:r,className:"w-full",children:u(dt,{})}),u(pt,{children:N(Ya,{children:[!s&&u(Oe,{value:"any",children:"不限"}),i.map(l=>u(Oe,{value:l.value,children:l.label},l.value))]})})]})]})}}}function hi({primary:e,more:t,values:a,onChange:o,onSearch:r,onReset:i,loading:s,currency:n,searchLabel:l="查询",searchIcon:c,disabled:f,prepend:k,append:w,note:S}){let[C,v]=gi(!1),P=(y,q)=>o({...a,[y]:q}),g=t.filter(y=>ia(y).some(q=>a[q])).length;return u(Zo,{children:u(qo,{children:N("form",{onSubmit:y=>{y.preventDefault(),r()},className:"flex flex-col gap-4",children:[N(Qt,{className:Jo,children:[k,e.map(y=>u(Yo,{spec:y,values:a,set:P,currency:n},y.id)),w]}),N(ge,{open:C,onOpenChange:v,children:[u(ve,{children:u(Qt,{className:Xo(Jo,"pb-4"),children:t.map(y=>u(Yo,{spec:y,values:a,set:P,currency:n},y.id))})}),N("div",{className:"flex flex-wrap items-center gap-2",children:[N(p,{type:"submit",disabled:s||f,children:[s?u(Y,{"data-icon":"inline-start"}):c??u(xi,{"data-icon":"inline-start"}),l]}),N(p,{type:"button",variant:"outline",onClick:i,children:[u(vi,{"data-icon":"inline-start"}),"重置"]}),t.length>0&&u(be,{asChild:!0,children:N(p,{type:"button",variant:"ghost",children:["更多条件",g?`(已填 ${g})`:"",u(bi,{"data-icon":"inline-end",className:Xo("transition-transform",C&&"rotate-180")})]})}),S&&u("p",{className:"text-xs text-muted-foreground sm:ml-auto",children:S})]})]})]})})})}import{Columns3Icon as Ci}from"lucide-react";import{jsx as ue,jsxs as Je}from"react/jsx-runtime";function yi({columns:e,visible:t,onChange:a,onReset:o}){return Je(Pe,{children:[ue(ke,{asChild:!0,children:Je(p,{variant:"outline",size:"sm",children:[ue(Ci,{"data-icon":"inline-start"}),"列设置"]})}),Je(Se,{align:"end",className:"max-h-96 w-56 overflow-y-auto",children:[Je(Ue,{children:["显示的列(",t.length,"/",e.length,")"]}),Je(Ke,{children:[ue(se,{onSelect:r=>(r.preventDefault(),o()),children:"恢复默认"}),ue(se,{onSelect:r=>(r.preventDefault(),a(e.map(i=>i.key))),children:"全部显示"})]}),ue(bt,{}),ue(Ke,{children:e.map(r=>ue(vo,{checked:t.includes(r.key),onSelect:i=>i.preventDefault(),onCheckedChange:i=>a(i?e.map(s=>s.key).filter(s=>s===r.key||t.includes(s)):t.filter(s=>s!==r.key)),children:r.label},r.key))})]})]})}import{useState as ki}from"react";import{cn as Q}from"cn";import{AlertDialog as ee}from"radix-ui";import{jsx as E,jsxs as Pi}from"react/jsx-runtime";function jo({...e}){return E(ee.Root,{"data-slot":"alert-dialog",...e})}function wi({...e}){return E(ee.Portal,{"data-slot":"alert-dialog-portal",...e})}function Ni({className:e,...t}){return E(ee.Overlay,{"data-slot":"alert-dialog-overlay",className:Q("fixed inset-0 z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",e),...t})}function Qo({className:e,size:t="default",...a}){return Pi(wi,{children:[E(Ni,{}),E(ee.Content,{"data-slot":"alert-dialog-content","data-size":t,className:Q("group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none max-w-[calc(100%-2rem)] sm:max-w-sm data-[size=sm]:sm:max-w-xs data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",e),...a})]})}function er({className:e,...t}){return E("div",{"data-slot":"alert-dialog-header",className:Q("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]",e),...t})}function tr({className:e,...t}){return E("div",{"data-slot":"alert-dialog-footer",className:Q("-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",e),...t})}function ar({className:e,...t}){return E(ee.Title,{"data-slot":"alert-dialog-title",className:Q("font-heading 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",e),...t})}function or({className:e,...t}){return E(ee.Description,{"data-slot":"alert-dialog-description",className:Q("text-sm text-balance text-muted-foreground md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",e),...t})}function rr({className:e,variant:t="default",size:a="default",...o}){return E(p,{variant:t,size:a,asChild:!0,children:E(ee.Action,{"data-slot":"alert-dialog-action",className:Q(e),...o})})}function nr({className:e,variant:t="outline",size:a="default",...o}){return E(p,{variant:t,size:a,asChild:!0,children:E(ee.Cancel,{"data-slot":"alert-dialog-cancel",className:Q(e),...o})})}import{jsx as J,jsxs as wt}from"react/jsx-runtime";function Si({open:e,onOpenChange:t,title:a,description:o,details:r,requireCheck:i,confirmLabel:s="确认",cancelLabel:n="取消",destructive:l,busy:c,onConfirm:f}){let[k,w]=ki(!1),S=!!i&&!k;return J(jo,{open:e,onOpenChange:C=>{C||w(!1),t(C)},children:wt(Qo,{children:[wt(er,{children:[J(ar,{children:a}),o&&J(or,{children:o})]}),r?.length?J("ul",{className:"list-disc space-y-1 pl-5 text-sm text-muted-foreground",children:r.map((C,v)=>J("li",{children:C},v))}):null,i&&wt(Be,{className:"flex items-start gap-2 text-sm font-normal",children:[J(de,{checked:k,onCheckedChange:C=>w(C===!0),className:"mt-0.5"}),J("span",{children:i})]}),wt(tr,{children:[J(nr,{children:n}),J(rr,{variant:l?"destructive":void 0,disabled:c||S,onClick:C=>{C.preventDefault(),!S&&f()},children:s})]})]})})}import{cva as Ri}from"class-variance-authority";import{cn as Ti}from"cn";import{Slot as Ii}from"radix-ui";import{jsx as Di}from"react/jsx-runtime";var zi=Ri("group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",{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 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover: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 ir({className:e,variant:t="default",asChild:a=!1,...o}){let r=a?Ii.Root:"span";return Di(r,{"data-slot":"badge","data-variant":t,className:Ti(zi({variant:t}),e),...o})}import{cn as Ai}from"cn";import{jsx as A,jsxs as U}from"react/jsx-runtime";var Mi={已完成:"border-emerald-600/40 bg-emerald-600/10 text-emerald-700 dark:text-emerald-400",需人工处理:"border-amber-600/40 bg-amber-600/10 text-amber-700 dark:text-amber-400",失败:"border-destructive/40 bg-destructive/10 text-destructive"};function Bi({task:e,running:t,onOpen:a,onStop:o,onRetry:r,className:i}){let s=e.budget&&(e.budget.used>0||e.budget.estimate)?e.budget.estimate?`${e.budget.used} / ${e.budget.estimate}${e.budget.unit??""}`:`${e.budget.used}${e.budget.unit??""}`:void 0;return U("div",{className:Ai("rounded-lg border p-3",i),children:[U("div",{className:"flex flex-wrap items-center gap-2",children:[A("button",{type:"button",className:"min-w-0 flex-1 truncate text-left font-medium text-primary underline-offset-4 hover:underline",onClick:a,children:e.code}),A(ir,{variant:"outline",className:Mi[e.status]??"",children:e.status||"—"})]}),(e.stage||e.hint)&&A("p",{className:"mt-1 text-xs text-muted-foreground",children:[e.stage,e.hint].filter(Boolean).join(" · ")}),e.stages?.length?A("div",{className:"mt-2 flex flex-wrap gap-1",children:e.stages.map(n=>U("span",{className:"rounded border px-1.5 py-0.5 text-xs tabular-nums",title:n.label,children:[n.label," ",n.pass,"/",n.input,n.todo?U("span",{className:"text-amber-600 dark:text-amber-400",children:[" +",n.todo]}):null]},n.key))}):null,U("dl",{className:"mt-2 grid grid-cols-2 gap-x-3 gap-y-1 text-xs text-muted-foreground",children:[s&&U("div",{className:"flex justify-between gap-2",children:[A("dt",{children:"算力"}),A("dd",{className:"tabular-nums",children:s})]}),e.rounds!=null&&U("div",{className:"flex justify-between gap-2",children:[A("dt",{children:"轮次"}),A("dd",{className:"tabular-nums",children:e.rounds})]}),e.startedAt&&U("div",{className:"flex justify-between gap-2",children:[A("dt",{children:"开始"}),A("dd",{className:"tabular-nums",children:e.startedAt})]}),e.lastActiveAt&&U("div",{className:"flex justify-between gap-2",children:[A("dt",{children:"最后活动"}),A("dd",{className:"tabular-nums",children:e.lastActiveAt})]})]}),U("div",{className:"mt-2 flex flex-wrap gap-1",children:[a&&A(p,{variant:"ghost",size:"sm",onClick:a,children:"查看"}),t&&o&&A(p,{variant:"ghost",size:"sm",onClick:o,children:"停止"}),r&&A(p,{variant:"ghost",size:"sm",onClick:r,children:"重试未完成"})]})]})}import{useEffect as dr,useRef as _i,useState as Gi}from"react";import{CheckIcon as Fi,CopyIcon as Oi}from"lucide-react";import{cn as sr}from"cn";import{ScrollArea as Ye}from"radix-ui";import{jsx as je,jsxs as Ei}from"react/jsx-runtime";function lr({className:e,children:t,...a}){return Ei(Ye.Root,{"data-slot":"scroll-area",className:sr("relative",e),...a,children:[je(Ye.Viewport,{"data-slot":"scroll-area-viewport",className:"size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1",children:t}),je(Li,{}),je(Ye.Corner,{})]})}function Li({className:e,orientation:t="vertical",...a}){return je(Ye.ScrollAreaScrollbar,{"data-slot":"scroll-area-scrollbar","data-orientation":t,orientation:t,className:sr("flex touch-none p-px transition-colors select-none data-horizontal:h-2.5 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-transparent data-vertical:h-full data-vertical:w-2.5 data-vertical:border-l data-vertical:border-l-transparent",e),...a,children:je(Ye.ScrollAreaThumb,{"data-slot":"scroll-area-thumb",className:"relative flex-1 rounded-full bg-border"})})}import{jsx as fe,jsxs as Nt}from"react/jsx-runtime";var Vi=/^\[(\d{4}-\d{2}-\d{2}T[\d:.]+Z)\]/;function $i(e,t){let a=e.match(Vi);if(!a)return e;let o=new Date(a[1]);return Number.isNaN(o.getTime())?e:`[${new Intl.DateTimeFormat("zh-CN",{timeZone:t,month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}).format(o)}]${e.slice(a[0].length)}`}function Hi({text:e,timeZone:t,className:a}){let o=String(e??"").trim(),r=o?o.split(`
|
|
2
|
+
`).map(c=>$i(c,t)):[],i=_i(null),[s,n]=Gi(!1);dr(()=>{i.current?.scrollIntoView({block:"nearest"})},[o]),dr(()=>{if(!s)return;let c=setTimeout(()=>n(!1),1500);return()=>clearTimeout(c)},[s]);async function l(){try{await navigator.clipboard.writeText(r.join(`
|
|
3
|
+
`)),n(!0)}catch{}}return Nt("section",{className:a,children:[Nt("div",{className:"mb-2 flex flex-wrap items-center gap-2",children:[fe("h3",{className:"text-sm font-medium",children:"工作流执行日志"}),fe("span",{className:"text-xs text-muted-foreground",children:"保留最近 50 条 · 时间按所选时区"}),o&&Nt(p,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>{l()},children:[s?fe(Fi,{"data-icon":"inline-start"}):fe(Oi,{"data-icon":"inline-start"}),s?"已复制":"复制"]})]}),o?Nt(lr,{className:"h-56 rounded border bg-muted/40",children:[fe("pre",{className:"whitespace-pre-wrap break-words p-3 text-xs leading-relaxed",children:r.join(`
|
|
4
|
+
`)}),fe("div",{ref:i})]}):fe("p",{className:"rounded border border-dashed p-3 text-xs text-muted-foreground",children:"暂无执行日志"})]})}import{CheckIcon as Ki,ChevronRightIcon as cr,LoaderIcon as Ui,SettingsIcon as Zi}from"lucide-react";import{cn as ta}from"cn";import{jsx as D,jsxs as Z}from"react/jsx-runtime";var qi={done:"bg-emerald-600 text-white border-emerald-600",active:"bg-primary text-primary-foreground border-primary",idle:"bg-muted text-muted-foreground border-border"};function pr(e){return e.input===0||e.input===e.pass+e.fail+e.todo}function Wi({startLabel:e="启动条件",startSummary:t,stages:a,countsOf:o,stateOf:r,current:i,onSelect:s,tail:n}){return Z("div",{className:"flex flex-col gap-2 lg:flex-row lg:items-stretch",children:[Z("div",{className:"flex min-w-0 items-center gap-2 rounded border bg-muted/40 px-3 py-2 lg:shrink-0",children:[D("span",{className:"flex size-6 shrink-0 items-center justify-center rounded-full border bg-background",children:D(Zi,{className:"size-3.5"})}),Z("div",{className:"min-w-0",children:[D("p",{className:"text-sm font-medium",children:e}),D("p",{className:"truncate text-xs text-muted-foreground",children:t})]})]}),a.map((l,c)=>{let f=r(l.key),k=o(l.key),w=i===l.key,S=pr(k);return Z("div",{className:"flex min-w-0 items-stretch gap-2 lg:shrink-0",children:[D(cr,{className:"hidden size-4 shrink-0 self-center text-muted-foreground lg:block"}),Z(p,{variant:w?"secondary":"ghost",onClick:()=>s(l.key),"aria-pressed":w,className:ta("h-auto w-full min-w-0 justify-start gap-2 border px-3 py-2 text-left lg:w-auto lg:min-w-40",w&&"border-primary"),children:[D("span",{className:ta("flex size-6 shrink-0 items-center justify-center rounded-full border text-xs",qi[f]),children:f==="done"?D(Ki,{className:"size-3.5"}):f==="active"?D(Ui,{className:"size-3.5 animate-spin"}):c+1}),Z("span",{className:"min-w-0 flex-1",children:[D("span",{className:"block text-sm font-medium",children:l.label}),Z("span",{className:"block text-xs tabular-nums text-muted-foreground",children:["输入 ",k.input," · 通过 ",D("span",{className:"text-emerald-600 dark:text-emerald-400",children:k.pass})," · 不通过"," ",k.fail," · 未完成 ",D("span",{className:ta(k.todo>0&&"text-amber-600 dark:text-amber-400"),children:k.todo})]}),!S&&D("span",{className:"block text-xs text-amber-600 dark:text-amber-400",children:"数不平,正在执行中"})]})]})]},l.key)}),n&&Z("div",{className:"flex min-w-0 items-stretch gap-2 lg:shrink-0",children:[D(cr,{className:"hidden size-4 shrink-0 self-center text-muted-foreground lg:block"}),Z("div",{className:"flex min-w-0 items-center gap-2 rounded border bg-muted/40 px-3 py-2 lg:min-w-32",children:[D("span",{className:"flex size-6 shrink-0 items-center justify-center rounded-full border bg-background",children:n.icon}),Z("div",{className:"min-w-0",children:[D("p",{className:"text-sm font-medium",children:n.label}),D("p",{className:"text-xs tabular-nums text-muted-foreground",children:n.summary})]})]})]})]})}export{Vt as AgentPanel,$t as AgentToggle,Vn as AppShell,Et as AppSidebar,qn as AuthGate,yi as ColumnPicker,Yt as ComboInput,Si as ConfirmDialog,li as DataPagination,oi as DataTable,hi as FilterPanel,_t as Markdown,Ho as PAGE_SIZE,Wi as StageProgress,Bi as TaskCard,Hi as TaskLog,Jn as ThemeProvider,Ut as TimezoneSelect,Zt as UserMenu,pr as countsBalanced,Ee as findNav};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { LucideIcon } from 'lucide-react';
|
|
2
|
+
|
|
3
|
+
interface NavItem {
|
|
4
|
+
title: string;
|
|
5
|
+
href: string;
|
|
6
|
+
}
|
|
7
|
+
interface NavGroup {
|
|
8
|
+
title: string;
|
|
9
|
+
icon: LucideIcon;
|
|
10
|
+
items: NavItem[];
|
|
11
|
+
}
|
|
12
|
+
/** 根据路径找出面包屑:[菜单组, 页面];菜单由模板传入 */
|
|
13
|
+
declare function findNav(nav: NavGroup[], pathname: string): {
|
|
14
|
+
group: NavGroup;
|
|
15
|
+
item: NavItem;
|
|
16
|
+
} | null;
|
|
17
|
+
|
|
18
|
+
/** 搜索条件的界面描述(选品页、选品库、自动任务弹窗共用) */
|
|
19
|
+
type UiFilterSpec = {
|
|
20
|
+
type: "range";
|
|
21
|
+
id: string;
|
|
22
|
+
label: string;
|
|
23
|
+
unit?: string;
|
|
24
|
+
price?: boolean;
|
|
25
|
+
} | {
|
|
26
|
+
type: "dateRange";
|
|
27
|
+
id: string;
|
|
28
|
+
label: string;
|
|
29
|
+
} | {
|
|
30
|
+
type: "text";
|
|
31
|
+
id: string;
|
|
32
|
+
label: string;
|
|
33
|
+
placeholder?: string;
|
|
34
|
+
} | {
|
|
35
|
+
type: "list";
|
|
36
|
+
id: string;
|
|
37
|
+
label: string;
|
|
38
|
+
placeholder?: string;
|
|
39
|
+
options?: string[];
|
|
40
|
+
multiple?: boolean;
|
|
41
|
+
} | {
|
|
42
|
+
type: "bool";
|
|
43
|
+
id: string;
|
|
44
|
+
label: string;
|
|
45
|
+
}
|
|
46
|
+
/** required:接口必填项,不提供「不限」选项 */
|
|
47
|
+
| {
|
|
48
|
+
type: "select";
|
|
49
|
+
id: string;
|
|
50
|
+
label: string;
|
|
51
|
+
options: {
|
|
52
|
+
value: string;
|
|
53
|
+
label: string;
|
|
54
|
+
}[];
|
|
55
|
+
required?: boolean;
|
|
56
|
+
}
|
|
57
|
+
/** 一组开关:Keepa 的 buyBoxIsFBA 这类参数只认 true,不选就是不限;值是选中项的逗号拼接 */
|
|
58
|
+
| {
|
|
59
|
+
type: "flags";
|
|
60
|
+
id: string;
|
|
61
|
+
label: string;
|
|
62
|
+
options: {
|
|
63
|
+
value: string;
|
|
64
|
+
label: string;
|
|
65
|
+
}[];
|
|
66
|
+
};
|
|
67
|
+
/** 表单值:range / dateRange 用 `${id}.gte` / `${id}.lte`,其它用 id */
|
|
68
|
+
type FilterValues = Record<string, string>;
|
|
69
|
+
declare function filterKeys(spec: {
|
|
70
|
+
type: string;
|
|
71
|
+
id: string;
|
|
72
|
+
}): string[];
|
|
73
|
+
/** flags 的值 → 选中项数组 */
|
|
74
|
+
declare function flagList(value: string | undefined): string[];
|
|
75
|
+
declare function toggleFlag(value: string | undefined, flag: string, on: boolean): string;
|
|
76
|
+
|
|
77
|
+
export { type FilterValues as F, type NavGroup as N, type UiFilterSpec as U, type NavItem as a, filterKeys as b, flagList as c, findNav as f, toggleFlag as t };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { A as AuthState } from '../auth-JoGZ-Tg-.js';
|
|
2
|
+
export { a as authIdentity, g as getApiKey, b as getAuthState, h as handleGatewayError, i as initialAuthState, l as loadApiKey, c as login, d as logout, m as maskApiKey, s as startAuth, e as subscribeAuth } from '../auth-JoGZ-Tg-.js';
|
|
3
|
+
import * as react from 'react';
|
|
4
|
+
|
|
5
|
+
declare function browserTimeZone(): string;
|
|
6
|
+
/** 传 null 表示恢复为浏览器时区 */
|
|
7
|
+
declare function setTimeZone(tz: string | null): void;
|
|
8
|
+
declare function useTimeZone(): string;
|
|
9
|
+
declare function useIsBrowserTimeZone(): boolean;
|
|
10
|
+
declare function timeZoneOffset(tz: string, date?: Date): string;
|
|
11
|
+
/** 指定时区下某天(yyyy-MM-dd,可偏移 addDays 天)0 点对应的时间戳 */
|
|
12
|
+
declare function zonedDayStart(date: string, tz: string, addDays?: number): number;
|
|
13
|
+
/** 按指定时区渲染日期时间 */
|
|
14
|
+
declare function formatDateTime(value: unknown, timeZone: string): string;
|
|
15
|
+
|
|
16
|
+
/** 页面声明给 LinkFox OS 的上下文:当前数据表 + 勾选的记录 */
|
|
17
|
+
interface AgentRecordRef {
|
|
18
|
+
id: string;
|
|
19
|
+
/** 一行摘要,方便 agent 和用户核对 */
|
|
20
|
+
label: string;
|
|
21
|
+
}
|
|
22
|
+
interface AgentPageContext {
|
|
23
|
+
/** 页面 / 数据来源,如「线索发现G1」「选品库」 */
|
|
24
|
+
source: string;
|
|
25
|
+
table?: {
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
};
|
|
29
|
+
records: AgentRecordRef[];
|
|
30
|
+
/** 记录 ID 的含义,默认「recordId」 */
|
|
31
|
+
idLabel?: string;
|
|
32
|
+
}
|
|
33
|
+
interface AgentNotebook {
|
|
34
|
+
notebookId: string;
|
|
35
|
+
name: string;
|
|
36
|
+
}
|
|
37
|
+
/** agent 任务结束后广播,页面据此刷新(agent 可能改了多维表) */
|
|
38
|
+
declare const AGENT_DONE_EVENT = "linkfox:agent-done";
|
|
39
|
+
interface AgentState {
|
|
40
|
+
open: boolean;
|
|
41
|
+
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
|
42
|
+
page: AgentPageContext | null;
|
|
43
|
+
setPage: (c: AgentPageContext | null) => void;
|
|
44
|
+
}
|
|
45
|
+
declare function AgentProvider({ children }: {
|
|
46
|
+
children: React.ReactNode;
|
|
47
|
+
}): react.JSX.Element;
|
|
48
|
+
declare function useAgent(): AgentState;
|
|
49
|
+
/** 页面调用:声明当前上下文,离开页面自动清除 */
|
|
50
|
+
declare function useAgentPageContext(ctx: AgentPageContext | null): void;
|
|
51
|
+
/** 把上下文拼到用户输入前面(仅首轮;续接轮由 sessionId 续接,会话里已有上下文) */
|
|
52
|
+
declare function buildAgentPrompt(input: string, ctx: AgentPageContext | null, notebook?: AgentNotebook): string;
|
|
53
|
+
declare const truncate: (s: string, n?: number) => string;
|
|
54
|
+
|
|
55
|
+
/** 登录态:与 runtime 的状态机共用同一份订阅 */
|
|
56
|
+
declare function useAuth(): AuthState;
|
|
57
|
+
|
|
58
|
+
export { AGENT_DONE_EVENT, type AgentNotebook, type AgentPageContext, AgentProvider, type AgentRecordRef, AuthState, browserTimeZone, buildAgentPrompt, formatDateTime, setTimeZone, timeZoneOffset, truncate, useAgent, useAgentPageContext, useAuth, useIsBrowserTimeZone, useTimeZone, zonedDayStart };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{a as n,b as s,c as u,d as a,e as b,f as d,g,h,i as j,j as k,k as q,l as v,m as w,n as y}from"../chunk-PZOYA4II.js";import{o,p as r,q as e,r as t,s as f,t as m,u as p,v as x,w as c,x as i,y as l}from"../chunk-5LS4UNRR.js";export{h as AGENT_DONE_EVENT,j as AgentProvider,t as authIdentity,n as browserTimeZone,v as buildAgentPrompt,g as formatDateTime,l as getApiKey,r as getAuthState,c as handleGatewayError,e as initialAuthState,m as loadApiKey,p as login,x as logout,i as maskApiKey,s as setTimeZone,f as startAuth,o as subscribeAuth,b as timeZoneOffset,w as truncate,k as useAgent,q as useAgentPageContext,y as useAuth,a as useIsBrowserTimeZone,u as useTimeZone,d as zonedDayStart};
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import { LinkfoxHttpError } from '@linkfox-web/http';
|
|
2
|
+
export { F as FilterValues, N as NavGroup, a as NavItem, U as UiFilterSpec, b as filterKeys, f as findNav, c as flagList, t as toggleFlag } from '../filter-spec-BHwe1PQ-.js';
|
|
3
|
+
import * as st from '@linkfox-web/ai-tools/smart-table';
|
|
4
|
+
import { FieldInput, NotebookInfo as NotebookInfo$1, TableInfo as TableInfo$1, RecordFilter, SmartRecord } from '@linkfox-web/ai-tools/smart-table';
|
|
5
|
+
export { Attachment, FieldInfo, FieldType, FilterCondition, ListRecordsResult as ListRecordsResponse, RecordFilter, SmartRecord } from '@linkfox-web/ai-tools/smart-table';
|
|
6
|
+
export { A as AuthState, a as authIdentity, g as getApiKey, b as getAuthState, h as handleGatewayError, i as initialAuthState, l as loadApiKey, c as login, d as logout, m as maskApiKey, s as startAuth, e as subscribeAuth } from '../auth-JoGZ-Tg-.js';
|
|
7
|
+
export { cn } from 'cn';
|
|
8
|
+
import 'lucide-react';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 模板注入的应用配置。
|
|
12
|
+
*
|
|
13
|
+
* 包内不读 `process.env`:Next 只对应用源码做静态内联,`node_modules` 里的环境变量
|
|
14
|
+
* 在构建后是 `undefined`。模板在自己的 `lib/app-kit.ts` 里读 env 并调用
|
|
15
|
+
* `configureAppKit()`,`NEXT_PUBLIC_*` 留在模板源码里才能被正确替换。
|
|
16
|
+
*/
|
|
17
|
+
interface AppKitConfig {
|
|
18
|
+
/** 工具网关地址;开启 rewrite 时模板传 `/api/linkfox` */
|
|
19
|
+
gatewayBaseUrl: string;
|
|
20
|
+
/** 第三方 SSO 服务地址 */
|
|
21
|
+
ssoBaseUrl: string;
|
|
22
|
+
/** SSO clientId;为空时只能走固定 API Key 模式 */
|
|
23
|
+
ssoClientId: string;
|
|
24
|
+
/** 是否开启同源 rewrite:决定 API Key 走 Authorization 还是 tool-gateway-api-key */
|
|
25
|
+
rewrite: boolean;
|
|
26
|
+
/** 固定 API Key。必须是函数,每次请求现取,不能缓存字符串 */
|
|
27
|
+
apiKey?: () => string | undefined;
|
|
28
|
+
/** 应用 ID(`apl` 开头);为空则跳过访问登记 */
|
|
29
|
+
applicationId?: string;
|
|
30
|
+
/** 子路径部署的前缀,用于拼 SSO 回调地址 */
|
|
31
|
+
basePath?: string;
|
|
32
|
+
}
|
|
33
|
+
declare function configureAppKit(next: AppKitConfig): void;
|
|
34
|
+
declare function appKitConfig(): AppKitConfig;
|
|
35
|
+
/** 每次调用都重新读取,避免把构建期之外的 Key 变化缓存住 */
|
|
36
|
+
declare function getConfiguredApiKey(): string | undefined;
|
|
37
|
+
|
|
38
|
+
declare const SESSION_EXPIRED_MESSAGE = "\u4F1A\u8BDD\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55";
|
|
39
|
+
/** 会话过期:上游 invalid_token(token 失效 / 过期 / 被吊销),或网关直接回 401 */
|
|
40
|
+
declare function isSessionExpired(e: unknown): boolean;
|
|
41
|
+
/** 前端自己判定的业务错误(生成超时、结果无法解析等),与 SDK 错误同一类型,errorMessage 统一处理 */
|
|
42
|
+
declare class LinkfoxError extends LinkfoxHttpError {
|
|
43
|
+
constructor(code: number, message: string);
|
|
44
|
+
}
|
|
45
|
+
declare function isAbortError(e: unknown): boolean;
|
|
46
|
+
/** 算力 / 余额不足:重试无意义,轮询时直接抛出 */
|
|
47
|
+
declare function isBalanceError(e: unknown): boolean;
|
|
48
|
+
/** 工具网关返回 401:配了固定 Key 时是 Key 失效,否则是登录态失效 */
|
|
49
|
+
declare function isApiKeyInvalid(e: unknown): boolean;
|
|
50
|
+
declare function errorMessage(e: unknown): string;
|
|
51
|
+
declare const sleep: (ms: number, signal?: AbortSignal) => Promise<void>;
|
|
52
|
+
|
|
53
|
+
/** 应用 ID 只来自配置;没配(或还是占位符)就整个功能跳过,不发任何请求 */
|
|
54
|
+
declare function getApplicationId(): string | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* 登录后登记一次「打开应用」,刷新用户的最近访问列表。
|
|
57
|
+
*
|
|
58
|
+
* 服务端 30 秒内重复上报只记一条流水,所以不用自己防抖,拿到会话时调一次即可。
|
|
59
|
+
* 匿名、应用不存在或在回收站时返回 recorded:false;网络失败会 reject——
|
|
60
|
+
* 两种都吞掉:登记失败不该把用户挡在门外。
|
|
61
|
+
*
|
|
62
|
+
* 直接调 SDK 而不经 gateway():那里会把 401 交给 handleGatewayError,
|
|
63
|
+
* 一个配错的应用 ID 就会把用户登出。
|
|
64
|
+
*/
|
|
65
|
+
declare function recordVisit(): void;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* 网关调用包装:错误统一交给 handleGatewayError 处理(会话过期 / Key 失效时提示并回到登录页)。
|
|
69
|
+
* 「200 + {error:{code,message}}」信封由 ai-tools 0.3.9 的 SDK 自己抛错,这里不再重复解析。
|
|
70
|
+
*/
|
|
71
|
+
declare function gateway<T>(p: Promise<T>): Promise<T>;
|
|
72
|
+
|
|
73
|
+
declare const AGENT_MODELS: readonly [{
|
|
74
|
+
readonly id: "default";
|
|
75
|
+
readonly name: "通用助手";
|
|
76
|
+
}, {
|
|
77
|
+
readonly id: "linkfox-product-selection-agent";
|
|
78
|
+
readonly name: "选品 Agent";
|
|
79
|
+
}, {
|
|
80
|
+
readonly id: "linkfox-market-analysis-agent";
|
|
81
|
+
readonly name: "市场分析 Agent";
|
|
82
|
+
}, {
|
|
83
|
+
readonly id: "linkfox-listing-agent";
|
|
84
|
+
readonly name: "Listing Agent";
|
|
85
|
+
}, {
|
|
86
|
+
readonly id: "linkfox-image-agent";
|
|
87
|
+
readonly name: "图片 Agent";
|
|
88
|
+
}, {
|
|
89
|
+
readonly id: "linkfox-video-agent";
|
|
90
|
+
readonly name: "视频 Agent";
|
|
91
|
+
}];
|
|
92
|
+
interface TaskStep {
|
|
93
|
+
id: string;
|
|
94
|
+
title: string;
|
|
95
|
+
status: "running" | "done" | "failed";
|
|
96
|
+
}
|
|
97
|
+
interface TaskFile {
|
|
98
|
+
name: string;
|
|
99
|
+
uri: string;
|
|
100
|
+
}
|
|
101
|
+
interface TaskView {
|
|
102
|
+
messageId: string;
|
|
103
|
+
/** 服务端会话 ID:下一轮追问时传回即可在同一会话内续接(技能 §6.3) */
|
|
104
|
+
sessionId: string;
|
|
105
|
+
steps: TaskStep[];
|
|
106
|
+
text: string;
|
|
107
|
+
files: TaskFile[];
|
|
108
|
+
/** 非空即结束:end_turn 为正常完成 */
|
|
109
|
+
stopReason: string;
|
|
110
|
+
}
|
|
111
|
+
declare function cancelTask(messageId: string): Promise<unknown>;
|
|
112
|
+
/** 任务结束后换取公开的完整过程链接(失败返回 undefined) */
|
|
113
|
+
declare function getShareUrl(messageId: string): Promise<string | undefined>;
|
|
114
|
+
/**
|
|
115
|
+
* 提交任务并轮询到结束;onUpdate 推送进行中的步骤与文本。
|
|
116
|
+
*
|
|
117
|
+
* 多轮对话:首轮不传 sessionId,服务端新建会话并在 create 响应里返回;
|
|
118
|
+
* 后续追问带上这个 sessionId,服务端在原会话内继续,Agent 保有前几轮上下文。
|
|
119
|
+
* 续接必须沿用同一个 modelId(会话属于发起它的专家),换专家要开新会话。
|
|
120
|
+
*/
|
|
121
|
+
declare function runTask(prompt: string, modelId: string, { signal, onUpdate, sessionId, }: {
|
|
122
|
+
signal?: AbortSignal;
|
|
123
|
+
onUpdate: (view: TaskView) => void;
|
|
124
|
+
/** 上一轮返回的 sessionId;首轮不传 */
|
|
125
|
+
sessionId?: string;
|
|
126
|
+
}): Promise<TaskView>;
|
|
127
|
+
|
|
128
|
+
type FieldDef = FieldInput;
|
|
129
|
+
type NotebookInfo = NotebookInfo$1;
|
|
130
|
+
/** 模板 `linkfox.config.ts` 的 `smartTableConfig` 结构(多数字段来自 `config/smart-table.json`) */
|
|
131
|
+
interface SmartTableFieldDef {
|
|
132
|
+
name: string;
|
|
133
|
+
type: string;
|
|
134
|
+
[key: string]: unknown;
|
|
135
|
+
}
|
|
136
|
+
interface SmartTableConfig {
|
|
137
|
+
/** 多维表(容器)名称 */
|
|
138
|
+
notebookName: string;
|
|
139
|
+
/** 多维表 id(nbk 开头):构建期由 NEXT_PUBLIC_NOTE_BOOK_ID 指定,留空则按名称查找 */
|
|
140
|
+
notebookId?: string;
|
|
141
|
+
/** 建多维表时的幂等键前缀,按应用区分 */
|
|
142
|
+
requestKeyPrefix?: string;
|
|
143
|
+
/** 数据表名称:key → 表名 */
|
|
144
|
+
tables: Record<string, string>;
|
|
145
|
+
/** 各数据表的列定义:ensureTable 建表/补列时使用 */
|
|
146
|
+
fields?: Record<string, readonly SmartTableFieldDef[]>;
|
|
147
|
+
}
|
|
148
|
+
/** 数据表信息 + 字段名 → fieldId(工作流触发条件要用) */
|
|
149
|
+
interface TableInfo extends TableInfo$1 {
|
|
150
|
+
fieldIds: Record<string, string>;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* 按模板的 `smartTableConfig` 建一套多维表客户端。
|
|
154
|
+
*
|
|
155
|
+
* 用工厂而不是模块级单例:包不能读宿主的环境变量,表结构也只能由模板注入。
|
|
156
|
+
* 模板的 `lib/app-kit.ts` 里 `setActiveSmartTable(createSmartTable(smartTableConfig))`,
|
|
157
|
+
* 包内组件(如 LinkFox OS 助手)通过 `activeSmartTable()` 拿到同一个实例。
|
|
158
|
+
*/
|
|
159
|
+
declare function createSmartTable<C extends SmartTableConfig>(config: C): {
|
|
160
|
+
config: C;
|
|
161
|
+
TABLE_FIELDS: Record<string, st.FieldInput[]>;
|
|
162
|
+
getNotebook: () => Promise<st.NotebookInfo>;
|
|
163
|
+
ensureTable: (key: string, fields?: FieldDef[]) => Promise<TableInfo>;
|
|
164
|
+
listRecords: (params: {
|
|
165
|
+
tableId: string;
|
|
166
|
+
page?: number;
|
|
167
|
+
perPage?: number;
|
|
168
|
+
fieldNames?: string[];
|
|
169
|
+
filter?: RecordFilter;
|
|
170
|
+
}) => Promise<st.ListRecordsResult>;
|
|
171
|
+
listAllRecords: (params: {
|
|
172
|
+
tableId: string;
|
|
173
|
+
fieldNames?: string[];
|
|
174
|
+
filter?: RecordFilter;
|
|
175
|
+
}, maxPages?: number) => Promise<st.SmartRecord[]>;
|
|
176
|
+
createRecords: (tableId: string, rows: Record<string, unknown>[]) => Promise<st.SmartRecord[]>;
|
|
177
|
+
updateRecords: (tableId: string, records: SmartRecord[]) => Promise<void>;
|
|
178
|
+
deleteRecords: (tableId: string, recordIds: string[]) => Promise<void>;
|
|
179
|
+
uploadAttachment: (tableId: string, recordId: string, fieldName: string, imageUrl: string) => Promise<st.Attachment>;
|
|
180
|
+
getRecord: (tableId: string, primaryField: string, primaryValue: string, recordId: string, fieldNames?: string[]) => Promise<st.SmartRecord | null>;
|
|
181
|
+
warmTables: () => Promise<TableInfo[]>;
|
|
182
|
+
tableIdOf: (key: string) => Promise<string>;
|
|
183
|
+
};
|
|
184
|
+
type SmartTable = ReturnType<typeof createSmartTable>;
|
|
185
|
+
/** 模板在 `lib/app-kit.ts` 里注册;包内组件用它读写多维表 */
|
|
186
|
+
declare function setActiveSmartTable(client: SmartTable): void;
|
|
187
|
+
declare function activeSmartTable(): SmartTable;
|
|
188
|
+
declare function isAttachmentList(v: unknown): v is st.Attachment[];
|
|
189
|
+
/** 附件 cell 的第一项(附件列是数组,业务上主图只存一张) */
|
|
190
|
+
declare function firstAttachment(v: unknown): st.Attachment | undefined;
|
|
191
|
+
/**
|
|
192
|
+
* 附件 cell 的临时访问地址。
|
|
193
|
+
* 地址由多维表每次读取时重签(约 3 小时有效),所以只能在渲染 / 调用接口的当下取,不要存。
|
|
194
|
+
* prefer=thumb 取缩略图(列表用),full 取原图(生图 / 生文输入用)。
|
|
195
|
+
*/
|
|
196
|
+
declare function attachmentUrl(v: unknown, prefer?: "thumb" | "full"): string | undefined;
|
|
197
|
+
/** 单元格取值工具 */
|
|
198
|
+
declare const str: (v: unknown) => string;
|
|
199
|
+
declare const num: (v: unknown) => number;
|
|
200
|
+
/** 逗号 / 换行分隔的文本列 → 数组 */
|
|
201
|
+
declare const splitList: (v: unknown) => string[];
|
|
202
|
+
/** 多维表 date 列写入用 */
|
|
203
|
+
declare const nowIso: () => string;
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* 工作流身份判定:**不靠名字**认「这条流是不是我这条模板流」。
|
|
207
|
+
*
|
|
208
|
+
* ## 为什么不能只按名字
|
|
209
|
+
*
|
|
210
|
+
* 复制多维表时工作流会跟着复制,而对方**保持原名**(缺陷 #5051 的产品结论),
|
|
211
|
+
* 于是一条从 `nbkA` 复制到 `nbkB` 的流仍叫 `Ozon选品-自动上架 (nbkA)`。
|
|
212
|
+
* 模板按自己的容器 id 算出 `(nbkB)`,`findByName` 必然落空 ⇒ 再建一整套。
|
|
213
|
+
* 线上实测副本容器里因此出现两套流、同表双触发。
|
|
214
|
+
*
|
|
215
|
+
* ## 三级判据
|
|
216
|
+
*
|
|
217
|
+
* 1. **硬判据:本容器已登记**。`listWorkflows({ notebookId })` 返回的就是侧栏那份关联数据;
|
|
218
|
+
* 「复制来的流」靠它进候选池,别的多维表下的同名流则进不来。
|
|
219
|
+
* ⚠️ 候选池 = 登记行 **∪ 精确名字**:**手动流不产生订阅、不登记**,只留登记行会让它们
|
|
220
|
+
* 每次打开页面都被判成「没部署」而无限新建。
|
|
221
|
+
* 2. **次判据:`description` 里的 `key=<模板key>`**。部署时由 `renderFlow` 写入,随复制一起走
|
|
222
|
+
* (复制只改 flowData 里的表引用,不动 description),所以副本流上它也在。
|
|
223
|
+
* 3. **兜底:名字**。复制来的流名字带的是**源**容器 id,所以放宽成「以 `<模板名> (` 开头」——
|
|
224
|
+
* **该放宽只在登记集合可用时生效**(否则等于回到今天那种会误认的匹配)。
|
|
225
|
+
*
|
|
226
|
+
* ## 什么时候降级
|
|
227
|
+
*
|
|
228
|
+
* - 没配 `NEXT_PUBLIC_NOTE_BOOK_ID`(自建部署):拿不到容器 id,整体退回**精确名字**匹配。
|
|
229
|
+
* - `listWorkflows` 查询失败:同上,退回精确名字匹配,不放松到前缀匹配。
|
|
230
|
+
*
|
|
231
|
+
* 两种情况都只是「回到改动前」,不会更糟。
|
|
232
|
+
*/
|
|
233
|
+
/** 认领只依赖这几个字段;模板自己的 `ChatflowSummary` 结构兼容即可(不要求索引签名)。 */
|
|
234
|
+
interface IClaimableFlow {
|
|
235
|
+
id: string;
|
|
236
|
+
name: string;
|
|
237
|
+
description?: string;
|
|
238
|
+
flowData?: string;
|
|
239
|
+
}
|
|
240
|
+
/** `listWorkflows` 里我们关心的部分。 */
|
|
241
|
+
interface IRegisteredWorkflow {
|
|
242
|
+
flowId: string;
|
|
243
|
+
/** null = 没绑触发表(手动 / 定时启动),不会被记录变化触发 */
|
|
244
|
+
tableId: string | null;
|
|
245
|
+
}
|
|
246
|
+
interface IWorkflowClaim<T extends IClaimableFlow> {
|
|
247
|
+
key: string;
|
|
248
|
+
flow?: T;
|
|
249
|
+
/** 命中依据,排查用:`key` / `name` / 无(未认领) */
|
|
250
|
+
matchedBy?: "key" | "name";
|
|
251
|
+
/** 同一个 key 还命中了别的流(历史重复流)。不自动删 —— 可能带用户手工修改 */
|
|
252
|
+
duplicates: T[];
|
|
253
|
+
}
|
|
254
|
+
/** 从流上取逻辑 key:先看 `description`,再看 `flowData` 里的 description。 */
|
|
255
|
+
declare function keyOf(flow: IClaimableFlow): string | undefined;
|
|
256
|
+
/**
|
|
257
|
+
* 把 `key=<key>` 补进 description。已经带了就不重复追加(幂等)。
|
|
258
|
+
*
|
|
259
|
+
* 部署时由 `renderFlow` 调用;「模板版本 <hash>」那段的格式不动,版本判定照旧。
|
|
260
|
+
*/
|
|
261
|
+
declare function withWorkflowKey(description: string, key: string): string;
|
|
262
|
+
/** 本多维表下的容器 id;没配就是 undefined(自建部署 / 未注入构建变量)。 */
|
|
263
|
+
declare function currentNotebookId(): string | undefined;
|
|
264
|
+
/**
|
|
265
|
+
* 读本容器已登记的关联。**永不抛**:失败返回 `null`,调用方据此退回精确名字匹配。
|
|
266
|
+
*/
|
|
267
|
+
declare function listRegisteredWorkflows(notebookId: string | undefined): Promise<IRegisteredWorkflow[] | null>;
|
|
268
|
+
/**
|
|
269
|
+
* 按上面的三级判据,为每个模板 key 挑出对应的流。
|
|
270
|
+
*
|
|
271
|
+
* @param names 模板 key → 展示名(`workflowNames`)
|
|
272
|
+
* @param flows 账号全量流(`listChatflows()` 的结果)
|
|
273
|
+
* @param links 本容器登记行;`null` = 查不到 / 未配容器 id ⇒ 退回精确名字匹配
|
|
274
|
+
*/
|
|
275
|
+
declare function claimWorkflows<T extends IClaimableFlow>(params: {
|
|
276
|
+
notebookId: string | undefined;
|
|
277
|
+
names: Record<string, string>;
|
|
278
|
+
flows: T[];
|
|
279
|
+
links: IRegisteredWorkflow[] | null;
|
|
280
|
+
}): Record<string, IWorkflowClaim<T>>;
|
|
281
|
+
/**
|
|
282
|
+
* 这条流的触发器是否**已关联到多维表**(侧栏能看到它、记录变更能触发它或定时任务挂在它下面)。
|
|
283
|
+
*
|
|
284
|
+
* 判据是「有没有登记行」,**不看 `tableId` 是否为 null**:定时流按设计只挂容器,
|
|
285
|
+
* 登记行的 `tableId` 就是 null(studio `14ca607` 起如此),拿它当「未生效」会把正常的定时流
|
|
286
|
+
* 全标成未关联。记录触发的流若确实没绑上表,由 studio 的 `tableSync` 那一侧报,
|
|
287
|
+
* 这里不重复猜。
|
|
288
|
+
*
|
|
289
|
+
* `links === null`(查询失败 / 未配容器 id)时返回 `undefined`(未知),不要猜。
|
|
290
|
+
*/
|
|
291
|
+
declare function isTriggerLinked(links: IRegisteredWorkflow[] | null, flowId: string | undefined): boolean | undefined;
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* 浏览器直接调用服务,兼容静态导出。SSO token 存进 http 会话,由 SDK 自动放进
|
|
295
|
+
* ai-tools 请求的 Authorization;api-user-center 按 clientId 存进独立 localStorage 键,
|
|
296
|
+
* 同域多个应用互不覆盖,也不覆盖主站 LINKFOX_AI_TOKEN。
|
|
297
|
+
*/
|
|
298
|
+
declare function initLinkfoxSdk(): void;
|
|
299
|
+
|
|
300
|
+
export { AGENT_MODELS, type AppKitConfig, type FieldDef, type IClaimableFlow, type IRegisteredWorkflow, type IWorkflowClaim, LinkfoxError, type NotebookInfo, SESSION_EXPIRED_MESSAGE, type SmartTable, type SmartTableConfig, type SmartTableFieldDef, type TableInfo, type TaskFile, type TaskStep, type TaskView, activeSmartTable, appKitConfig, attachmentUrl, cancelTask, claimWorkflows, configureAppKit, createSmartTable, currentNotebookId, errorMessage, firstAttachment, gateway, getApplicationId, getConfiguredApiKey, getShareUrl, initLinkfoxSdk, isAbortError, isApiKeyInvalid, isAttachmentList, isBalanceError, isSessionExpired, isTriggerLinked, keyOf, listRegisteredWorkflows, nowIso, num, recordVisit, runTask, setActiveSmartTable, sleep, splitList, str, withWorkflowKey };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as S,b as K,c as O,d as z,e as p,f as M,g as Q,h as V,i as X,j as Z,k as ee,l as w,m as te,n as re,o as oe,p as ne,q as ie,r as se,s as le}from"../chunk-TU6CZIZF.js";import{a as b,b as T,c as W,d as h,e as C,f as R,g as $,h as F,i as L,j as B,k as N,l as D,m as E,n as I,o as P,p as j,q as v,r as A,s as J,t as U,u as Y,v as _,w as q,x as G,y as H}from"../chunk-5LS4UNRR.js";import*as g from"@linkfox-web/ai-tools/smart-table";var a=/key=([a-z0-9][a-z0-9-]*)/i;function y(e){let t=a.exec(e.description??"")?.[1];if(t)return t.toLowerCase();try{let r=JSON.parse(e.flowData??"{}");return a.exec(r.description??"")?.[1]?.toLowerCase()}catch{return}}function de(e,t){if(a.test(e))return e;let r=e.trim();return r?`${r};key=${t}`:`key=${t}`}function ce(){return w().config.notebookId||void 0}async function me(e){if(!e)return null;try{return((await p(g.listWorkflows({notebookId:e}))).workflows??[]).map(r=>({flowId:r.flowId,tableId:r.tableId??null}))}catch{return null}}function ue(e){let{notebookId:t,names:r,flows:k,links:d}=e,c=d?new Set(d.map(n=>n.flowId)):null,i={};for(let[n,s]of Object.entries(r)){let x=t?`${s} (${t})`:s,m=o=>o.name===x,u=k.filter(o=>(c?.has(o.id)??!1)||m(o)),l=u.filter(o=>y(o)===n.toLowerCase());if(l.length){i[n]={key:n,flow:l[0],matchedBy:"key",duplicates:l.slice(1)};continue}let f=u.filter(o=>m(o)||(c&&t&&o.name.startsWith(`${s} (`))===!0);i[n]=f.length?{key:n,flow:f[0],matchedBy:"name",duplicates:f.slice(1)}:{key:n,duplicates:[]}}return i}function pe(e,t){if(!(!e||!t))return e.some(r=>r.flowId===t)}import{cn as Le}from"cn";export{M as AGENT_MODELS,R as LinkfoxError,h as SESSION_EXPIRED_MESSAGE,w as activeSmartTable,T as appKitConfig,oe as attachmentUrl,A as authIdentity,Q as cancelTask,ue as claimWorkflows,Le as cn,b as configureAppKit,Z as createSmartTable,ce as currentNotebookId,B as errorMessage,S as filterKeys,z as findNav,re as firstAttachment,K as flagList,p as gateway,H as getApiKey,D as getApplicationId,j as getAuthState,W as getConfiguredApiKey,V as getShareUrl,q as handleGatewayError,I as initLinkfoxSdk,v as initialAuthState,$ as isAbortError,L as isApiKeyInvalid,te as isAttachmentList,F as isBalanceError,C as isSessionExpired,pe as isTriggerLinked,y as keyOf,me as listRegisteredWorkflows,U as loadApiKey,Y as login,_ as logout,G as maskApiKey,le as nowIso,ie as num,E as recordVisit,X as runTask,ee as setActiveSmartTable,N as sleep,se as splitList,J as startAuth,ne as str,P as subscribeAuth,O as toggleFlag,de as withWorkflowKey};
|
package/package.json
CHANGED
|
@@ -1,6 +1,93 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linkfox-web/app-kit",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "LinkFox 应用模板公共运行时与组件:登录门禁、多维表客户端、列表/筛选/任务组件、LinkFox OS 助手",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://git.ziniao.com/a58-linkfoxagent/linkfox-agent/linkfox-frontend-sdk.git",
|
|
8
|
+
"directory": "packages/app-kit"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"main": "./dist/runtime/index.js",
|
|
12
|
+
"types": "./dist/runtime/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
"./runtime": {
|
|
15
|
+
"types": "./dist/runtime/index.d.ts",
|
|
16
|
+
"default": "./dist/runtime/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./react": {
|
|
19
|
+
"types": "./dist/react/index.d.ts",
|
|
20
|
+
"default": "./dist/react/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./components": {
|
|
23
|
+
"types": "./dist/components/index.d.ts",
|
|
24
|
+
"default": "./dist/components/index.js"
|
|
25
|
+
},
|
|
26
|
+
"./styles.css": "./styles.css"
|
|
27
|
+
},
|
|
28
|
+
"typesVersions": {
|
|
29
|
+
"*": {
|
|
30
|
+
"runtime": [
|
|
31
|
+
"./dist/runtime/index.d.ts"
|
|
32
|
+
],
|
|
33
|
+
"react": [
|
|
34
|
+
"./dist/react/index.d.ts"
|
|
35
|
+
],
|
|
36
|
+
"components": [
|
|
37
|
+
"./dist/components/index.d.ts"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"dist",
|
|
43
|
+
"styles.css"
|
|
44
|
+
],
|
|
45
|
+
"sideEffects": [
|
|
46
|
+
"*.css"
|
|
47
|
+
],
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"cn": "0.4.0"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"class-variance-authority": "^0.7.1",
|
|
53
|
+
"cmdk": "^1.1.1",
|
|
54
|
+
"lucide-react": "^1.56.0",
|
|
55
|
+
"next": ">=16.4.3",
|
|
56
|
+
"next-themes": "^0.4.6",
|
|
57
|
+
"radix-ui": "^1.8.1",
|
|
58
|
+
"react": "^19.3.0",
|
|
59
|
+
"react-dom": "^19.3.0",
|
|
60
|
+
"react-markdown": "^10.1.0",
|
|
61
|
+
"remark-gfm": "^4.0.1",
|
|
62
|
+
"sonner": "^2.0.8",
|
|
63
|
+
"@linkfox-web/ai-tools": "^0.3.9",
|
|
64
|
+
"@linkfox-web/http": "^0.3.7",
|
|
65
|
+
"@linkfox-web/api-user-center": "^0.3.7"
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@types/react": "19.3.0",
|
|
69
|
+
"@types/react-dom": "19.3.0",
|
|
70
|
+
"class-variance-authority": "0.7.1",
|
|
71
|
+
"cmdk": "1.1.1",
|
|
72
|
+
"lucide-react": "1.56.0",
|
|
73
|
+
"next": "16.4.3",
|
|
74
|
+
"next-themes": "0.4.6",
|
|
75
|
+
"radix-ui": "1.8.1",
|
|
76
|
+
"react": "19.3.0",
|
|
77
|
+
"react-dom": "19.3.0",
|
|
78
|
+
"react-markdown": "10.1.0",
|
|
79
|
+
"remark-gfm": "4.0.1",
|
|
80
|
+
"sonner": "2.0.8",
|
|
81
|
+
"@linkfox-web/ai-tools": "0.3.9",
|
|
82
|
+
"@linkfox-web/http": "0.3.7",
|
|
83
|
+
"@linkfox-web/api-user-center": "0.3.7"
|
|
84
|
+
},
|
|
85
|
+
"publishConfig": {
|
|
86
|
+
"access": "public"
|
|
87
|
+
},
|
|
88
|
+
"license": "MIT",
|
|
89
|
+
"scripts": {
|
|
90
|
+
"build": "tsup",
|
|
91
|
+
"typecheck": "tsc -p tsconfig.json"
|
|
92
|
+
}
|
|
6
93
|
}
|