@rexvane/piweb 0.3.19 → 0.3.20
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/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +4 -4
- package/.next/build-manifest.json +3 -3
- package/.next/prerender-manifest.json +3 -3
- package/.next/react-loadable-manifest.json +1 -1
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +1 -1
- package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/api/remote/route.js +2 -2
- package/.next/server/app/api/update/route.js +1 -1
- package/.next/server/app/api/version/route.js +1 -1
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +3 -3
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +3 -3
- package/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login.html +1 -1
- package/.next/server/app/login.rsc +2 -2
- package/.next/server/app/login.segments/_full.segment.rsc +2 -2
- package/.next/server/app/login.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +4 -4
- package/.next/server/chunks/496.js +1 -1
- package/.next/server/chunks/924.js +2 -2
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/4686-b1e9fa876d0ea671.js +1 -0
- package/.next/static/chunks/839.d3fe337a9117c325.js +1 -0
- package/.next/static/chunks/webpack-3614a8337843456b.js +1 -0
- package/package.json +1 -1
- package/src/app/api/remote/route.ts +12 -2
- package/src/components/RemoteSection.tsx +41 -8
- package/src/i18n.tsx +8 -6
- package/src/lib/remote/mobile-proxy.ts +8 -2
- package/src/lib/remote/supervisor.ts +18 -8
- package/.next/static/chunks/4686-e3825f3b6a384aa1.js +0 -1
- package/.next/static/chunks/839.7403c6bdace4c56c.js +0 -1
- package/.next/static/chunks/webpack-bd2b9202ecbcdcaa.js +0 -1
- /package/.next/static/{JDGSR-TIbk9qZWcUNYIX3 → _Y3Lq0lI5RJ1tFSOnDi0L}/_buildManifest.js +0 -0
- /package/.next/static/{JDGSR-TIbk9qZWcUNYIX3 → _Y3Lq0lI5RJ1tFSOnDi0L}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
exports.id=496,exports.ids=[496],exports.modules={104:(a,b,c)=>{Promise.resolve().then(c.t.bind(c,81921,23)),Promise.resolve().then(c.t.bind(c,60440,23)),Promise.resolve().then(c.t.bind(c,84342,23)),Promise.resolve().then(c.t.bind(c,82265,23)),Promise.resolve().then(c.t.bind(c,35421,23)),Promise.resolve().then(c.t.bind(c,61335,23)),Promise.resolve().then(c.t.bind(c,70664,23)),Promise.resolve().then(c.bind(c,74661))},1096:(a,b,c)=>{Promise.resolve().then(c.t.bind(c,95547,23))},8e3:(a,b,c)=>{"use strict";c.d(b,{N:()=>e,h:()=>f});var d=c(48249);function e({size:a=18,className:b,style:c}){return(0,d.jsxs)("svg",{width:a,height:a,viewBox:"165.29 165.29 469.43 469.43","aria-hidden":!0,className:b,style:{color:"var(--dsw-label-primary)",display:"block",flex:"none",...c},children:[(0,d.jsx)("path",{fill:"currentColor",fillRule:"evenodd",d:"M165.29 165.29 H517.36 V400 H400 V517.36 H282.65 V634.72 H165.29 Z M282.65 282.65 V400 H400 V282.65 Z"}),(0,d.jsx)("path",{fill:"currentColor",d:"M517.36 400 H634.72 V634.72 H517.36 Z"})]})}function f({compact:a=!1}){return a?(0,d.jsx)(e,{size:18}):(0,d.jsxs)("div",{className:"inline-flex items-center select-none",style:{color:"var(--dsw-label-primary)",gap:6},children:[(0,d.jsx)(e,{size:17}),(0,d.jsx)("span",{className:"inline-flex items-center",style:{fontSize:16.5,fontWeight:600,letterSpacing:"-0.02em",color:"var(--dsw-label-primary)",lineHeight:1},children:"pi"}),(0,d.jsx)("span",{className:"inline-flex items-center justify-center font-bold",style:{fontSize:9.5,letterSpacing:"0.06em",height:15,paddingLeft:4.5,paddingRight:4.5,borderRadius:4,background:"var(--dsw-label-primary)",color:"var(--dsw-bg-base)",lineHeight:1,textTransform:"uppercase"},children:"HARNESS"})]})}},18874:()=>{},23635:()=>{},36552:(a,b,c)=>{Promise.resolve().then(c.t.bind(c,95547,23)),Promise.resolve().then(c.t.bind(c,15098,23)),Promise.resolve().then(c.t.bind(c,47644,23)),Promise.resolve().then(c.t.bind(c,33859,23)),Promise.resolve().then(c.t.bind(c,98099,23)),Promise.resolve().then(c.t.bind(c,16237,23)),Promise.resolve().then(c.t.bind(c,98562,23)),Promise.resolve().then(c.t.bind(c,36675,23))},36593:()=>{},55091:(a,b,c)=>{"use strict";Object.defineProperty(b,"__esModule",{value:!0}),Object.defineProperty(b,"default",{enumerable:!0,get:function(){return f}});let d=c(5735),e=c(22675);function f(){return(0,d.jsx)(e.HTTPAccessErrorFallback,{status:404,message:"This page could not be found."})}("function"==typeof b.default||"object"==typeof b.default&&null!==b.default)&&void 0===b.default.__esModule&&(Object.defineProperty(b.default,"__esModule",{value:!0}),Object.assign(b.default,b),a.exports=b.default)},59645:(a,b,c)=>{"use strict";function d(){return[{type:"image/svg+xml",sizes:"any",url:"/icon.svg?779ce17318f43f72"}]}c.r(b),c.d(b,{default:()=>d})},60587:()=>{},61135:()=>{},76537:(a,b,c)=>{"use strict";c.r(b),c.d(b,{default:()=>g,metadata:()=>e,viewport:()=>f});var d=c(5735);c(18874),c(36593),c(61135);let e={title:"pi",description:"Web UI for the pi coding agent"},f={width:"device-width",initialScale:1,themeColor:[{media:"(prefers-color-scheme: light)",color:"#fcfbf9"},{media:"(prefers-color-scheme: dark)",color:"#2e3440"}]};function g({children:a}){return(0,d.jsx)("html",{lang:"zh-CN",suppressHydrationWarning:!0,children:(0,d.jsx)("body",{suppressHydrationWarning:!0,children:a})})}},78335:()=>{},87944:(a,b,c)=>{Promise.resolve().then(c.t.bind(c,81921,23))},93961:(a,b,c)=>{"use strict";c.d(b,{I18nProvider:()=>i,s:()=>j});var d=c(48249),e=c(67484);let f={confirm:"确认",cancel:"取消",delete:"删除",rename:"重命名",renameSession:"重命名会话",renameWorkspace:"重命名工作区",search:"搜索",save:"保存",close:"关闭",error:"出错",copy:"复制",copyFailed:"复制失败",externalImage:"外部图片,点击加载",chatWidthHandle:"拖动调整对话宽度",editMessage:"编辑这条消息",sendEdit:"重新发送",editMessageFailed:"编辑重发失败",export:"导出",settings:"设置",newChat:"新会话",reconnecting:"连接中断,正在重连…",sessionListLoadFailed:"会话列表加载失败",retry:"重试",compacting:"正在压缩上下文…",compactionComplete:"上下文压缩完成",compactionFailed:"上下文压缩失败",pickWorkspaceFirst:"请先选择工作区",capacityFields:"容量",contextWindowLabel:"上下文窗口",maxTokensLabel:"最大输出",capacityHint:"留空用默认 \xb7 支持 256K / 2M 写法",capacityInvalid:"第 {n} 行:容量需为数字(可用 K/M)",discoverEmpty:"远端没有返回可识别的模型",candidateTitle:"发现 {count} 个模型,勾选要添加的",candidateAll:"全选",candidatePicked:"已选 {n} 个",candidateAdopt:"添加 {n} 个",runningTool:"Running {name}…",thinkingLive:"Thinking",stepRunning:"Running",stepRan:"已运行",stepRead:"读取",stepSearched:"搜索",stepEdited:"编辑了",stepWrote:"写入了",resultRead:"读取了 {n} 行",resultFound:"找到 {n} 处",resultWrote:"{n} 行",sumThought:"思考了 {d}",sumRan:"运行了 {n} 条命令",sumRan1:"运行了 {n} 条命令",sumRead:"读了 {n} 个文件",sumRead1:"读了 {n} 个文件",sumSearched:"搜索了 {n} 次",sumSearched1:"搜索了 {n} 次",sumJoin:",",toolLines:"{n} 行",toolMatches:"{n} 个匹配",toolExit:"退出码 {code}",toolWritten:"已写入",diffSummary:"+{add} −{del} 行",deletedFile:"已删除 {path}",backToBottom:"回到底部",modeSteer:"插话",modeQueue:"排队",sendSteer:"插话:当前工具跑完就送达",sendQueue:"排队:本轮结束后发送",queueEdit:"↑ 取回编辑",queueDrop:"丢弃",viewInTrajectory:"在轨迹中查看",turnRanFor:"耗时 {duration}",durationSeconds:"{seconds} 秒",durationMinutes:"{minutes} 分 {seconds} 秒",clockMd:"{m}月{d}日",clockYmd:"{y}年{m}月{d}日",turnUsageTitle:"本回合用量",filesPanel:"文件",outline:"大纲",moreActions:"更多",filesFilter:"筛选文件…",filesShowAll:"显示 node_modules 等",filesHideNoise:"隐藏 node_modules 等",fileReference:"引用到输入框",fileOpenEditor:"在编辑器中打开",fileChangedByPi:"本会话中被 pi 修改",fileRenderMarkdown:"渲染",fileRawSource:"源码",gitUnavailable:"未找到 git 命令,请确认已安装并加入 PATH。",gitUpstream:"上游 {name}",gitNoUpstream:"无上游分支",gitConflict:"冲突",gitAskCommit:"让 pi 提交",gitDetails:"Git 详情",gitAskCommitPrompt:"请检查当前工作区的变更,把相关改动分组提交,写清晰的 commit message。",gitDiffEmpty:"没有差异",gitDiffTruncated:"差异过长,已截断",gitBinary:"二进制文件,不显示差异",gitStagedDiff:"暂存区差异",gitWorktreeDiff:"工作区差异",gitNoCommits:"尚无提交",gitBack:"返回",gitPanel:"Git",panelRefresh:"刷新",panelLoading:"加载中…",filesEmpty:"空目录",filesBack:"返回",fileBinary:"二进制文件,不提供预览",filePreviewTruncated:"文件较大,仅显示前 256 KB",entriesTruncated:"目录条目过多,仅显示前 2000 项",gitNotRepo:"此工作区不是 Git 仓库。",gitDetached:"分离头指针",gitAhead:"领先 {n}",gitBehind:"落后 {n}",gitStaged:"已暂存",gitUnstaged:"未暂存",gitUntracked:"未跟踪",gitNoChanges:"工作区干净,没有变更",gitStatusUnknown:"Git 状态读取失败,无法确认是否有变更",gitRecentCommits:"最近提交",toolNoOutput:"无输出",toolFailed:"失败",thinkingClamped:"当前模型不支持「{requested}」,已改为「{level}」",modelError:"模型返回错误",modelErrorTimes:"连续 {n} 次",modelErrorRateLimit:"限流:请求过于频繁,稍等片刻再试",modelErrorBilling:"余额或配额不足",modelErrorAuth:"鉴权失败:检查该供应商的 API Key",modelErrorNotFound:"模型不存在或当前 Key 无权访问",modelErrorContext:"上下文超出模型窗口,可用 /compact 压缩后重试",modelErrorTimeout:"请求超时",modelErrorServer:"供应商服务端出错或过载",modelErrorModeration:"请求内容被供应商审核拦截(敏感词),换措辞或新开会话试试",modelErrorNetwork:"网络连接失败",turnAborted:"已中止",moreLines:"还有 {n} 行",commandLines:"{n} 行脚本",thinkLabel:"思考",expandOutput:"展开全部输出",expandDiff:"展开改动",collapseOutput:"收起",workspaces:"工作区",pickFolderTitle:"选择工作区文件夹",pickFolderUp:"上一级",pickFolderConfirm:"选择此文件夹",pickFolderEmpty:"此目录下没有子文件夹",pickFolderTruncated:"只列出前 {n} 个文件夹",pickFolderLoading:"读取中…",searchSessions:"搜索会话...",addWorkspace:"添加工作区",groupBy:"分组方式",sortBy:"排序方式",byWorkspace:"按工作区",flatList:"单列表",manualOrder:"按创建时间",recentUpdated:"最近更新",newSessionHere:"在此工作区新会话",removeWorkspace:"从列表移除",deleteWorkspace:"删除工作区",deleteWorkspaceConfirm:"将把“{name}”从工作区列表中移除。文件夹与会话记录会保留,其会话将显示在“未分组”下。",deleteWorkspacePending:"正在删除工作区…",workspaceNameConflict:"已存在名为“{name}”的工作区。",ungrouped:"未分组",forkSession:"在新对话中分支",archiveSession:"归档会话",unarchiveSession:"取消归档",archivedSessions:"已归档",deleteAllSessions:"删除全部会话",deleteAllConfirm:"删除此工作区的全部会话?不可恢复。",contextInject:"上下文注入",autoCompact:"自动压缩",settingsLoading:"正在读取设置…",settingsLoadFailed:"设置读取失败;未显示默认值。请重试。",settingsSaveFailed:"设置未保存,请检查输入或网络后重试。",settingsRetry:"重试",autoCompactDesc:"上下文超出阈值时自动压缩历史",reserveTokens:"保留 Token",keepRecentTokens:"近期保留",autoRetry:"自动重试",autoRetryDesc:"请求失败后的自动重试",maxRetries:"最大重试次数",baseDelayMs:"初始延迟 (ms)",reloadExtensions:"重载全部扩展",cycleModel:"循环切换模型",cycleModelHint:"循环模型(Shift 点击切换到前一个)",branches:"分支",noBranches:"暂无可跳转的分支节点",oauthLogin:"OAuth 登录",authMethod:"认证方式",webAuth:"访问认证",webAuthTokenOn:"已启用(启动令牌)",loginTokenTitle:"这个实例用启动令牌登录",loginTokenDesc:"请打开启动 PiWeb 时终端里打印的登录链接(形如 …/?token=…)。令牌每次重启都会更换;打开一次后浏览器会记住 30 天。",logout:"退出登录",authMethodApiKey:"API 密钥",oauthDevicePrompt:"请在浏览器中完成授权",oauthOpenAuth:"打开授权页面",oauthDeviceCode:"设备码",oauthCodeCopied:"已复制",usageQuotaLabel:"API 配额",usageRequests:"请求",usageRefresh:"刷新配额",usageProbe:"检测配额",usageProbing:"检测中…",usageProbeDisclosure:"检测会向 xAI 发送一次可能计费的最小请求。",usageProbeFailed:"配额检测失败,未获得用量信息。",usagePlan:"套餐",usageQuotaRemaining:"额度剩余",queryingQuota:"正在查询额度…",usageReadOnlyDisclosure:"读取提供商的只读用量端点,不消耗额度。",usageReset:"刷新时间",usageWindowWeekly:"周限",usageWindowMonthly:"月限",usageWindowHours:"{n} 小时",usageWindowDays:"{n} 天",usageWindowRolling:"滚动窗口",usageWindowChat:"对话",usageWindowCompletions:"补全",usageWindowPremium:"高级请求",usageVariantOpus:"Opus",usageVariantCode:"代码",usageBalanceGranted:"赠金",usageBalanceToppedUp:"充值",usageBalanceVoucher:"代金券",usageBalanceCash:"现金",usageBalanceUsed:"已用",usageBalanceLimit:"上限",oauthWait:"等待授权…",oauthCancel:"取消登录",noSessions:"暂无会话",startWith:"新建工作区",inputPlaceholder:"给 pi 发消息…",thinking:"思考",thinkingOff:"关闭",model:"模型",selectModel:"选择模型",triggerLoading:"正在加载模型…",blockedComposer:"当前模型不可用,请先选择模型",emptyModels:"没有可用的模型。",emptyEfforts:"当前模型未提供推理等级。",thinkingUnsupported:"此模型不支持",thinkingUnsupportedHint:'模型没有声明推理能力。自定义模型请在 ~/.pi/agent/models.json 里给该模型加 "reasoning": true(可选 thinkingLevelMap 指定档位)',toolReadonly:"Read Only",toolStandard:"Workspace Write",toolFull:"Full access",stop:"停止",send:"发送",imageAttachment:"图片附件",imageTooLarge:"单张图片不能超过 20 MB",imageCountLimit:"一次最多添加 20 张图片",imageTypeUnsupported:"仅支持 JPEG、PNG、WebP 和 GIF 图片",dropToAttach:"松开添加附件",dropToAttachHint:"图片直接附到消息;其他文件(压缩包/文档等)保存后以路径引用,模型可用工具读取",dropLimits:"图片 ≤ 20MB \xb7 最多 20 张 \xb7 其他文件 ≤ 100MB \xb7 最多 16 个",uploading:"正在上传…",uploadFailed:"上传失败",uploadTooLarge:"单个文件不能超过 100 MB",uploadCountLimit:"一次最多添加 16 个文件",attachmentLine:"附件:{path}({size})",cmdMenu:"命令",slashCatalog:"命令与技能",skillType:"技能",cmdCompact:"压缩更早的对话历史",cmdExport:"下载本会话日志",cmdModel:"选择本会话使用的模型",cmdNew:"新建会话",cmdFork:"分叉会话",cmdReload:"重载扩展、技能与提示模板(pi /reload)",promptType:"模板",extensionCmdType:"扩展",cmdUnknown:"没有这个命令:/{name}。可用命令见输入框的 / 菜单",extensionDialogTag:"扩展",extensionStatus:"扩展状态",contextUsed:"上下文已用",contextUnknown:"上下文用量未知",contextSystem:"系统提示词",contextMessages:"对话消息",contextTools:"工具",promptPanel:"提示词来源",promptRefresh:"刷新",promptLoading:"加载中…",promptColdHint:"会话尚未启动:先列出磁盘上的提示词文件;打开会话后才会出现「组装后的系统提示词」与工具定义。",promptOriginProject:"项目",promptOriginAgent:"个人",promptOriginPackage:"包",promptOriginExtension:"扩展",promptKindSystem:"系统提示词文件",promptKindAppend:"追加提示词",promptKindAgents:"项目记忆(AGENTS.md)",promptKindSkill:"技能提示词",promptKindTemplate:"提示模板",promptKindTool:"工具提示词",promptKindAssembled:"系统提示词",promptKindCompacted:"压缩摘要",promptCompactedKey:"进入上下文的压缩摘要",promptGuidelines:"提示词指南",promptParameters:"参数定义",promptAssembledKey:"当前生效的系统提示词",promptToolBuiltin:"内置",promptToolExtension:"扩展",contextSystemPrompt:"System Prompt",contextSystemTools:"System Tools",contextCustomTools:"Custom Tools",contextMemory:"Memory(AGENTS.md)",contextSkills:"Skills",contextUserMessages:"User Messages",contextAgentText:"Agent Text",contextAgentThinking:"Agent Thinking",contextAgentToolCall:"Agent Tool Call",contextToolOutput:"Tool Output",contextCompacted:"Compacted Data",contextAutoCompactBuffer:"Auto-Compact Buffer",contextFreeSpace:"Free Space",turns:"轮次",toolCalls:"工具调用",cost:"花费",duration:"耗时",cacheHits:"缓存命中",statsCounts:"{turns} 轮 \xb7 {steps} 步",ttftAverage:"首 token 平均",inputTokens:"输入",outputTokens:"输出",tabChat:"对话",tabTrajectory:"轨迹",sessionLog:"Session log",sessionDetails:"会话详情",exportJsonl:"导出 JSONL",trajTimeline:"时间轴",trajModeSeq:"等距",trajModeTime:"时间",trajModeDur:"间隔",trajEmpty:"本会话还没有轨迹记录",trajSearchPlaceholder:"搜索轨迹",trajNoMatch:"没有匹配的轨迹记录",trajInput:"输入",trajModel:"模型",trajTools:"工具",trajOutput:"输出",trajThink:"思考",trajTime:"时间",trajTurn:"轮次",trajSystem:"系统",trajSession:"会话",trajSummary:"摘要",trajPreview:"预览",trajRaw:"原始",trajSource:"来源",trajStatus:"状态",trajCompleted:"已完成",trajFailed:"失败",trajStarted:"开始时间",trajTokens:"Token 用量",trajNoContent:"此记录没有可显示的内容",encodingLossWarning:"这段历史工具输出在写入时已经损坏,无法恢复的行已隐藏。当前 Pi SDK 已对新的 PowerShell 输出强制使用 UTF-8。",ttft:"首 token",decode:"解码",inspector:"记录详情",setGeneral:"通用设置",setModels:"模型",enterBehavior:"繁忙时 Enter 键行为",enterBehaviorDesc:"仅在 pi 运行时生效;Ctrl/Cmd+Enter 用另一种方式发送",enterQueue:"排队:本轮结束后发送",enterSteer:"插话:当前工具跑完就送达",setSkills:"技能",importSessions:"导入会话",importDesc:"把本机 Codex / Claude Code / Grok / ZCode / dsh / opencode 的对话无损导入成 pi 会话:文本、思考、工具调用与结果、时间戳、用量都保留。源项目目录还在本机就导回原工作区,否则落到下面选的兜底工作区。只读源数据,不修改源工具的任何文件。",importRescan:"重新扫描",importScanning:"扫描中…",importSourceClaude:"Claude Code",importSourceCodex:"Codex",importSourceGrok:"Grok",importSourceZcode:"ZCode",importSourceDsh:"dsh",importSourceOpencode:"opencode",importSourceError:"{source} 扫描失败:{message}",importGroupCount:"{n} 条 \xb7 已导入 {imported}",importPickSource:"选择来源",importLimitHint:"每个来源只列最近 {n} 条对话(更早的会话不扫描,省时省资源)",importLimitHintTooltip:"看更早的会话:把 src/lib/session-import/index.ts 里的 SCAN_LIMIT_PER_SOURCE 调大",importSelectAll:"全选本组",importSelectNone:"清空本组",importClearSelection:"清空选择",importRun:"导入所选 ({n})",importRunning:"导入中…",importFallbackWorkspace:"兜底工作区",importFallbackHint:"原项目目录已不在本机时落到这里",importWhereGoes:"导入去向",importGoesOriginal:"回到原工作区",importGoesFallback:"原目录已不在,用兜底工作区",importAlready:"已导入",importUntitled:"(无标题)",importNoProject:"(无项目目录)",importMessages:"{n} 条消息",importEmpty:"没有找到可导入的本地会话",importReportSummary:"成功 {imported} \xb7 跳过 {skipped} \xb7 失败 {failed}",drawerPanel:"右侧抽屉",drawerSections:"抽屉入口",drawerPrompts:"提示词",setPlugins:"插件",setRemote:"远程连接",remoteBuiltin:"内置插件",remoteLanTitle:"局域网入口",remoteLanHint:"同一个 WiFi 下的设备直接打开下面地址即可,手机排版已适配。默认开启。",remotePublicTitle:"公网入口",remotePublicHint:"开启后任何浏览器都能打开,无需安装客户端。地址由 Cloudflare 随机分配,每次启动都会变。",remoteStart:"开启远程连接",remoteStop:"关闭",remoteWorking:"启动中…",remoteRunning:"运行中",remoteStopped:"未开启",remotePending:"地址已生成,生效中…",remoteEngineMissing:"找不到 cloudflared。请安装后重试,或用 PIWEB_CLOUDFLARED 指定它的路径。",remoteFailed:"操作失败",remoteBlockedAuth:"认证没开,远程连接不可用:开出去就是一个免密入口。请用 piweb 启动器启动,或设 PI_WEB_AUTH=1。",remoteBlockedDev:"开发模式只服务本机,远程连接不可用。请先构建,再用生产模式启动。",remoteSessionsTitle:"已登录的设备",remoteSessionsHint:"手机、别的电脑登录后一直有效(30 天)。设备丢了或链接被别人拿到时,可以让所有设备(包括这台)都要重新用启动令牌登录。",remoteSignOutAll:"让所有设备重新登录",remoteSignOutAllConfirm:"再点一次确认",appearance:"外观",appearanceMode:"亮暗模式",themeLight:"浅色",themeDark:"深色",themeSystem:"跟随系统",themeSilverSteel:"银钢",themeLimestoneCoal:"石灰与煤炭",themeLinenMoss:"亚麻与苔绿",themeNordPaper:"北欧纸墨",themePebrel:"Pebrel",themeDsh:"海与墨",fontSize:"正文字号",fontUiSize:"界面字体",fontUiSizeDesc:"侧栏、按钮、标签等界面文字",fontChatSize:"对话字体",fontChatSizeDesc:"消息正文、用户气泡与输入框",fontUiFamily:"界面字体族",fontUiFamilyDesc:"侧栏、按钮、标签等界面文字使用的字体",fontMonoFamily:"代码字体族",fontMonoFamilyDesc:"代码块、diff、行内代码使用的等宽字体",fontCustom:"自定义…",fontCustomPlaceholder:"输入字体栈,如 Fira Code, monospace",language:"界面语言",openConfigFile:"打开配置文件",providerAuthOk:"已配置",providerReady:"请求认证可用",authUnavailable:"凭据不可用",credentialSource:"凭据:{source}",authSourceRuntime:"运行时",authSourceEnvironment:"环境变量",authSourceCommand:"models.json 命令",authSourceProvider:"Provider 配置",apiKey:"API Key",apiKeyStored:"已保存;留空保持不变",providerIdImmutable:"Provider ID 创建后不可修改;如需更名,请删除后重建。",modelConfigReopen:"模型配置已保存并立即生效;正在回答的会话在本轮结束后生效。",customModelIdentityNotice:"自定义模型 ID 只是发往该 API 地址的路由名;PiWeb 不会自动下载、接入或识别本机 Ollama 模型。",customApiKeyHint:"可留空改用 auth.json;指向本机/私网的无鉴权服务(Ollama 等)保存时自动填占位值。",modelsTitle:"模型",modelsDesc:"填入各提供方的 API 密钥即可使用其模型。",addProvider:"添加提供方",addCustomProvider:"添加自定义提供方",customProviderTitle:"自定义提供方",edit:"编辑",customBadge:"自定义",providerLabel:"提供方",apiType:"API 类型",modelsList:"模型(每行一个 ID)",baseUrl:"Base URL",apiAddress:"API 地址",apiProtocol:"API 协议",apiKeyOptional:"输入 API 密钥,或留空使用环境认证",customSettings:"自定义设置",providerDefault:"提供方默认",selectProvider:"选择提供方",searchProviders:"搜索提供方名称或 ID",noProviderMatches:"没有匹配的提供方",modelCount:"{count} 个模型",providerId:"Provider ID",providerIdHint:"以小写字母开头的标识,在请求中唯一标识该提供方,并用于派生凭据名。",providerIdInvalid:"只能使用小写字母、数字和单个连字符分段。",providerIdTaken:"该 Provider ID 已存在。",displayName:"显示名称",displayNameOptional:"显示名称(可选)",modelCatalog:"模型目录",discoverModels:"获取可用模型",allowPrivateDiscovery:"允许本机/私网",allowPrivateHint:"模型地址指向本机或私有网络(如 Ollama、LM Studio、one-api 本地网关)时勾选,本次探测放行;发消息不受此限制",discoveringModels:"获取中...",usingDefaultModels:"正在使用 Pi SDK 默认模型 \xb7 {count} 个",customModelsRequired:"至少添加一个可发送的模型 ID",modelCatalogEmptyBuiltin:"未添加覆盖模型;模型选择器会继续实时使用 Pi SDK 的官方模型目录。",modelCatalogEmptyCustom:"模型选择器中将不显示任何模型;请至少添加一个模型 ID。",addModel:"添加模型",modelId:"模型 ID",createProvider:"创建提供方",saving:"保存中...",setKey:"保存 Key",removeKey:"移除 Key",removeOAuth:"移除 OAuth",confirmRemoveOAuth:"确定移除“{name}”的 OAuth 登录吗?移除后需重新登录才能使用。",confirmRemoveProvider:"确定删除提供方“{name}”及其配置吗?",confirmRemoveKey:"确定移除“{name}”的已保存密钥吗?",customProviders:"自定义 Provider(models.json)",toolsSection:"工具启用情况",toolsSectionDesc:"三档预设决定新会话的默认工具;打开会话后可逐个启停当前会话的工具(仅本会话生效)。",toolsCurrentSession:"当前会话",toolsActiveCount:"{n}/{total} 已启用",toolsNoSession:"打开一个会话后,这里会显示可用工具并支持逐个启停。",securityToolPreset:"权限",securityToolPresetDesc:"切换当前会话工具集;Workspace Write 包含 bash,并非文件系统沙箱",securityTrust:"项目信任",securityTrustDesc:"首次进入含 .pi/ 资源的项目时是否自动信任(写入 pi settings.json)",trustAsk:"每次询问",trustAlways:"总是信任",trustNever:"从不信任",versionPiweb:"PiWeb 版本",versionPiwebDesc:"本 Web 应用的版本,点击打开仓库",versionPi:"Pi 版本",versionPiDesc:"pi 智能体内核的版本,点击打开仓库",checkUpdate:"检查更新",checkingUpdate:"检查中…",upToDate:"已是最新",updateTo:"更新到 {v}",updatingNow:"更新中…",updatedTo:"已更新到 {v},重启 PiWeb 后生效",updateFailed:"更新失败",updateManualHint:"先停止 piweb,再执行上面的命令(Windows 无法替换运行中的安装目录)",skillsDesc:"关闭后技能不会出现在系统提示中,仅可通过 /skill:名称 手动调用",confirmDeleteSkill:"确定删除技能“{name}”吗?将删除其所在技能目录,不可恢复。",deleteSkillHint:"删除技能目录",skillDeletePackageHint:"包技能请用禁用管理",scopeGlobal:"全局",scopeProject:"项目",scopePackage:"包",viewSkillFile:"查看 SKILL.md",packages:"已安装的 pi 包",packagesEmpty:"尚未安装任何 pi 包",addPackage:"安装 pi 包",addPackagePlaceholder:"npm:包名 / git:https://… / 本地路径",installLocal:"安装到当前项目(-l)",install:"安装",uninstall:"卸载",confirmUninstallPackage:"确定卸载“{source}”吗?",update:"更新",pluginConfig:"插件配置",pluginList:"插件列表",pluginPageDesc:"配置和查看本部署已安装的插件。",searchPlugins:"搜索插件",enabled:"已启用",disabled:"已停用",enablePlugin:"启用",disablePlugin:"停用",updating:"正在更新...",uninstalling:"正在卸载...",updateSuccess:"更新成功",uninstallSuccess:"已卸载",extensionsEmpty:"没有已加载的扩展",extensionLoadError:"加载失败",resourceDiagnostics:"资源诊断",installing:"正在安装…",installSuccess:"已安装并加载",reloadedSessions:"已重载:{loaders} 个加载器 \xb7 {sessions} 个会话",projectTrustBanner:"此项目含 .pi/ 扩展或技能,pi 需要你的信任才会加载并执行它们",projectTrustBannerNever:"此项目的 .pi/ 扩展与技能已被设为不信任,不会加载",projectTrustAllow:"信任并加载",projectTrustDeny:"不信任",projectTrustForget:"重新询问",projectTrustTrusted:"项目已信任",projectTrustUntrusted:"项目未信任",resources:"携带",toastSaved:"已保存",toastError:"操作失败",running:"运行中",projectPanel:"项目",growthScopeRound:"本轮",growthScopeSession:"本会话累计",growthOnlyChanges:"只看改动",growthPickRound:"选择轮次",growthRoundJump:"输入轮号...",growthRoundJumpHint:"输入轮号后按回车跳到该轮",growthPrev:"上一轮",growthNext:"下一轮",growthRoundPosition:"第 {current}/{total} 轮",growthRecordNow:"立即记录:把当前改动记为「你的修改」",growthRecordNone:"没有新的改动",growthNoRounds:"还没有记录。发一条消息让 pi 开始工作,每一轮的改动会出现在这里。",growthLoading:"正在读取记录…",growthNoChangesRound:"本轮无文件改动",growthNoSession:"打开或新建一个会话后,这里会显示项目的生长过程。",growthUnavailable:"机器上找不到 git,项目生长功能不可用",growthUnavailableFallback:"生长记录不可用(找不到可用的 git),已显示当前目录结构",growthConsentTitle:"要为这个工作区开启生长记录吗?",growthConsentNotGit:"生长记录会把 pi 每一轮的改动存成 git 提交,方便回看和对比。这个目录还不是 git 仓库,开启后会在这里执行 git init(新建 .git 目录)。",growthConsentNested:"生长记录会把 pi 每一轮的改动存成 git 提交,方便回看和对比。这个目录是另一个仓库({parent})的子目录,开启后会在这里再建一个嵌套的 git 仓库,外层仓库会把它当成一个子仓库看待。",growthConsentNote:"记录挂在专用引用 refs/piweb/rounds/… 上,不动分支和暂存区。选择会按工作区记住。",growthConsentAllow:"开启并建仓库",growthConsentDecline:"不记录",growthRoundLabel:"第 {n} 轮",growthKindUser:"你的修改",growthRoundFiles:"{n} 个文件",growthJumpToChat:"在对话里看",growthRunning:"本轮进行中…",growthStatusAborted:"已中止",growthStatusError:"出错",growthStatD:"删除",growthPending:"生成中",growthLazyDir:"当前磁盘条目,不在所选这一轮的记录中",growthTruncated:"这一轮变更过多,只显示前 2000 条",chatRoundChanged:"本轮改了 {n} 个文件",chatRoundNoChanges:"本轮没有改动文件",chatRoundShow:"在项目栏里查看这一轮",growthExpandAll:"展开全部",growthCollapseAll:"收起全部",growthFilter:"筛选…",viewerModeDiff:"变更",viewerModeContent:"内容",viewerModeRender:"渲染",viewerFold:"折叠未改动",viewerUnfold:"展开未改动",viewerFoldedLines:"\xb7\xb7\xb7 {n} 行未改动 \xb7\xb7\xb7",viewerPrevChange:"上一处改动",viewerNextChange:"下一处改动",viewerFullscreen:"全屏",viewerExitFullscreen:"退出全屏",viewerQuickOpen:"输入文件名打开…",viewerQuickOpenEmpty:"没有匹配的文件",viewerNoChanges:"这一范围内此文件没有变化",viewerDeleted:"此文件在本轮被删除,显示的是删除前的内容",viewerHistorical:"此文件已不在当前快照中,显示最近一次记录的内容",viewerMissing:"此文件已不在当前快照或磁盘中",viewerPatchTruncated:"差异过大,已截断",viewerCloseTab:"关闭页签",viewerNotInSnapshot:"此文件不在快照里(超过 1MB 或被排除),显示磁盘上的当前内容",viewerLoadFailed:"加载失败",viewerEmpty:"从左侧树里选择一个文件"},g={zh:f,en:{confirm:"Confirm",cancel:"Cancel",delete:"Delete",rename:"Rename",renameSession:"Rename session",renameWorkspace:"Rename workspace",search:"Search",save:"Save",close:"Close",error:"Error",copy:"Copy",copyFailed:"Copy failed",externalImage:"External image — click to load",chatWidthHandle:"Drag to resize the conversation",editMessage:"Edit this message",sendEdit:"Send again",editMessageFailed:"Edit and resend failed",export:"Export",settings:"Settings",newChat:"New session",reconnecting:"Connection lost, reconnecting…",sessionListLoadFailed:"Failed to load sessions",retry:"Retry",compacting:"Compacting context…",compactionComplete:"Context compaction complete",compactionFailed:"Context compaction failed",pickWorkspaceFirst:"Select a workspace first",capacityFields:"Capacities",contextWindowLabel:"Context window",maxTokensLabel:"Max output",capacityHint:"blank = default \xb7 256K / 2M accepted",capacityInvalid:"Row {n}: capacity must be a number (K/M ok)",discoverEmpty:"No recognizable models returned",candidateTitle:"Found {count} models — pick ones to add",candidateAll:"Select all",candidatePicked:"{n} selected",candidateAdopt:"Add {n}",runningTool:"Running {name}…",thinkingLive:"Thinking",stepRunning:"Running",stepRan:"Ran",stepRead:"Read",stepSearched:"Searched",stepEdited:"Edited",stepWrote:"Wrote",resultRead:"Read {n} lines",resultFound:"Found {n} matches",resultWrote:"{n} lines",sumThought:"Thought for {d}",sumRan:"ran {n} shell commands",sumRan1:"ran {n} shell command",sumRead:"read {n} files",sumRead1:"read {n} file",sumSearched:"searched {n} times",sumSearched1:"searched once",sumJoin:", ",toolLines:"{n} lines",toolMatches:"{n} matches",toolExit:"exit {code}",toolWritten:"written",diffSummary:"+{add} −{del} lines",deletedFile:"deleted {path}",backToBottom:"Back to bottom",modeSteer:"steer",modeQueue:"queue",sendSteer:"Steer: delivered after the current tool call",sendQueue:"Queue: sent after this turn ends",queueEdit:"↑ Edit queued",queueDrop:"Discard",viewInTrajectory:"View in trajectory",turnRanFor:"ran for {duration}",durationSeconds:"{seconds}s",durationMinutes:"{minutes}m {seconds}s",clockMd:"{m}/{d}",clockYmd:"{y}/{m}/{d}",turnUsageTitle:"Turn usage",filesPanel:"Files",outline:"Outline",moreActions:"More",filesFilter:"Filter files…",filesShowAll:"Show node_modules etc.",filesHideNoise:"Hide node_modules etc.",fileReference:"Reference in composer",fileOpenEditor:"Open in editor",fileChangedByPi:"Modified by pi in this session",fileRenderMarkdown:"Render",fileRawSource:"Source",gitUnavailable:"git command not found. Install it and make sure it is on PATH.",gitUpstream:"upstream {name}",gitNoUpstream:"no upstream",gitConflict:"Conflicts",gitAskCommit:"Ask pi to commit",gitDetails:"Git details",gitAskCommitPrompt:"Review the current changes, group related edits into commits, and write clear commit messages.",gitDiffEmpty:"No differences",gitDiffTruncated:"Diff truncated",gitBinary:"Binary file, no diff shown",gitStagedDiff:"Staged diff",gitWorktreeDiff:"Working tree diff",gitNoCommits:"No commits yet",gitBack:"Back",gitPanel:"Git",panelRefresh:"Refresh",panelLoading:"Loading…",filesEmpty:"Empty directory",filesBack:"Back",fileBinary:"Binary file, no preview",filePreviewTruncated:"Large file, showing first 256 KB only",entriesTruncated:"Too many entries, showing first 2000",gitNotRepo:"This workspace is not a Git repository.",gitDetached:"detached HEAD",gitAhead:"ahead {n}",gitBehind:"behind {n}",gitStaged:"Staged",gitUnstaged:"Unstaged",gitUntracked:"Untracked",gitNoChanges:"Working tree clean",gitStatusUnknown:"Git status unavailable; changes could not be determined",gitRecentCommits:"Recent commits",toolNoOutput:"no output",toolFailed:"failed",thinkingClamped:'This model does not support "{requested}"; using "{level}" instead',modelError:"Model returned an error",modelErrorTimes:"{n} times in a row",modelErrorRateLimit:"Rate limited: too many requests, wait a moment and retry",modelErrorBilling:"Insufficient balance or quota",modelErrorAuth:"Authentication failed: check this provider's API key",modelErrorNotFound:"Model not found or not accessible with this key",modelErrorContext:"Context exceeds the model window; try /compact and retry",modelErrorTimeout:"Request timed out",modelErrorServer:"Provider server error or overloaded",modelErrorModeration:"Request blocked by the provider's content filter (sensitive words); rephrase or start a new session",modelErrorNetwork:"Network connection failed",turnAborted:"Aborted",moreLines:"{n} more lines",commandLines:"{n}-line script",thinkLabel:"Thought",expandOutput:"Show full output",expandDiff:"Show changes",collapseOutput:"Collapse",workspaces:"Workspaces",pickFolderTitle:"Choose a workspace folder",pickFolderUp:"Parent folder",pickFolderConfirm:"Use this folder",pickFolderEmpty:"No subfolders here",pickFolderTruncated:"Showing the first {n} folders",pickFolderLoading:"Loading…",searchSessions:"Search sessions...",addWorkspace:"Add workspace",groupBy:"Group by",sortBy:"Sort by",byWorkspace:"Workspace",flatList:"Flat list",manualOrder:"Created",recentUpdated:"Recently updated",newSessionHere:"New session here",removeWorkspace:"Remove from list",deleteWorkspace:"Delete workspace",deleteWorkspaceConfirm:'Remove "{name}" from the workspace list. Folders and session records will be retained, and its sessions will be displayed under "Ungrouped".',deleteWorkspacePending:"Deleting workspace...",workspaceNameConflict:'A workspace named "{name}" already exists.',ungrouped:"Ungrouped",forkSession:"Fork session",archiveSession:"Archive session",unarchiveSession:"Unarchive",archivedSessions:"Archived",deleteAllSessions:"Delete all sessions",deleteAllConfirm:"Delete ALL sessions in this workspace? This cannot be undone.",contextInject:"Context",autoCompact:"Auto compaction",settingsLoading:"Loading settings…",settingsLoadFailed:"Settings could not be loaded. Defaults are not shown; please retry.",settingsSaveFailed:"Settings were not saved. Check the value or connection and retry.",settingsRetry:"Retry",autoCompactDesc:"Automatically compact history when context exceeds the threshold",reserveTokens:"Reserve tokens",keepRecentTokens:"Keep recent",autoRetry:"Auto retry",autoRetryDesc:"Automatically retry failed requests",maxRetries:"Max retries",baseDelayMs:"Initial delay (ms)",reloadExtensions:"Reload all extensions",cycleModel:"Cycle model",cycleModelHint:"Cycle model (Shift-click for previous)",branches:"Branches",noBranches:"No branch points available",oauthLogin:"OAuth login",authMethod:"Authentication",webAuth:"Access authentication",webAuthTokenOn:"Enabled (launch token)",loginTokenTitle:"This instance signs in with a launch token",loginTokenDesc:"Open the login link printed in the terminal when PiWeb started (…/?token=…). The token changes on every restart; once opened, the browser remembers it for 30 days.",logout:"Sign out",authMethodApiKey:"API key",oauthDevicePrompt:"Finish authorization in your browser",oauthOpenAuth:"Open authorization page",oauthDeviceCode:"Device code",oauthCodeCopied:"Copied",usageQuotaLabel:"API quota",usageRequests:"Requests",usageRefresh:"Refresh quota",usageProbe:"Check quota",usageProbing:"Checking…",usageProbeDisclosure:"Checking sends one minimal request to xAI that may be billed.",usageProbeFailed:"Quota check failed; no usage data was returned.",usagePlan:"Plan",usageQuotaRemaining:"Remaining quota",queryingQuota:"Querying quota…",usageReadOnlyDisclosure:"Reads the provider's read-only usage endpoint; consumes no quota.",usageReset:"Resets",usageWindowWeekly:"Weekly",usageWindowMonthly:"Monthly",usageWindowHours:"{n}h",usageWindowDays:"{n}d",usageWindowRolling:"Rolling",usageWindowChat:"Chat",usageWindowCompletions:"Completions",usageWindowPremium:"Premium requests",usageVariantOpus:"Opus",usageVariantCode:"Code",usageBalanceGranted:"Granted",usageBalanceToppedUp:"Topped up",usageBalanceVoucher:"Voucher",usageBalanceCash:"Cash",usageBalanceUsed:"Used",usageBalanceLimit:"Limit",oauthWait:"Waiting for authorization…",oauthCancel:"Cancel login",noSessions:"No sessions yet",startWith:"New workspace",inputPlaceholder:"Message pi…",thinking:"Thinking",thinkingOff:"Off",model:"Model",selectModel:"Select model",triggerLoading:"Loading models…",blockedComposer:"This model is unavailable — select one to continue",emptyModels:"No models available.",emptyEfforts:"This model provides no reasoning effort levels.",thinkingUnsupported:"Not supported by this model",thinkingUnsupportedHint:'The model does not declare reasoning support. For custom models, add "reasoning": true (optionally a thinkingLevelMap) to the model in ~/.pi/agent/models.json',toolReadonly:"Read Only",toolStandard:"Workspace Write",toolFull:"Full access",stop:"Stop",send:"Send",imageAttachment:"Image attachment",imageTooLarge:"Each image must be 20 MB or smaller",imageCountLimit:"You can attach up to 20 images",imageTypeUnsupported:"Only JPEG, PNG, WebP, and GIF images are supported",dropToAttach:"Drop to attach",dropToAttachHint:"Images attach to the message; other files (archives, documents) are saved and referenced by path for the agent to read",dropLimits:"Images ≤ 20MB \xb7 up to 20 \xb7 Other files ≤ 100MB \xb7 up to 16",uploading:"Uploading…",uploadFailed:"Upload failed",uploadTooLarge:"Each file must be 100 MB or smaller",uploadCountLimit:"You can attach up to 16 files",attachmentLine:"Attachment: {path} ({size})",cmdMenu:"Commands",slashCatalog:"Commands and skills",skillType:"Skill",cmdCompact:"Compact older conversation history",cmdExport:"Download this session log",cmdModel:"Select the model for this session",cmdNew:"Start a new session",cmdFork:"Fork this session",cmdReload:"Reload extensions, skills and prompt templates (pi /reload)",promptType:"Template",extensionCmdType:"Extension",cmdUnknown:"Unknown command: /{name}. See the / menu in the composer for available commands",extensionDialogTag:"Extension",extensionStatus:"Extension status",contextUsed:"context used",contextUnknown:"Context usage unknown",contextSystem:"System prompt",contextMessages:"Messages",contextTools:"Tools",promptPanel:"Prompt sources",promptRefresh:"Refresh",promptLoading:"Loading…",promptColdHint:"Session not started yet: disk files are listed now; the assembled system prompt and tool definitions appear once the session is running.",promptOriginProject:"project",promptOriginAgent:"user",promptOriginPackage:"package",promptOriginExtension:"extension",promptKindSystem:"System prompt file",promptKindAppend:"Appended prompt",promptKindAgents:"Project memory (AGENTS.md)",promptKindSkill:"Skill prompts",promptKindTemplate:"Prompt templates",promptKindTool:"Tool prompts",promptKindAssembled:"System prompt",promptKindCompacted:"Compaction summary",promptCompactedKey:"Compaction summary in context",promptGuidelines:"Prompt guidelines",promptParameters:"Parameter schema",promptAssembledKey:"Effective system prompt",promptToolBuiltin:"builtin",promptToolExtension:"extension",contextSystemPrompt:"System Prompt",contextSystemTools:"System Tools",contextCustomTools:"Custom Tools",contextMemory:"Memory (AGENTS.md)",contextSkills:"Skills",contextUserMessages:"User Messages",contextAgentText:"Agent Text",contextAgentThinking:"Agent Thinking",contextAgentToolCall:"Agent Tool Call",contextToolOutput:"Tool Output",contextCompacted:"Compacted Data",contextAutoCompactBuffer:"Auto-Compact Buffer",contextFreeSpace:"Free Space",turns:"turns",toolCalls:"tool calls",cost:"cost",duration:"duration",cacheHits:"cache hits",statsCounts:"{turns} turns \xb7 {steps} steps",ttftAverage:"TTFT avg",inputTokens:"Input",outputTokens:"Output",tabChat:"Chat",tabTrajectory:"Trajectory",sessionLog:"Session log",sessionDetails:"Session details",exportJsonl:"Export JSONL",trajTimeline:"Timeline",trajModeSeq:"Sequence",trajModeTime:"Time",trajModeDur:"Duration",trajEmpty:"No trajectory records yet",trajSearchPlaceholder:"Search trajectory",trajNoMatch:"No matching trajectory records",trajInput:"Input",trajModel:"Model",trajTools:"Tools",trajOutput:"Output",trajThink:"Think",trajTime:"Time",trajTurn:"Turn",trajSystem:"System",trajSession:"Session",trajSummary:"Summary",trajPreview:"Preview",trajRaw:"Raw",trajSource:"Source",trajStatus:"Status",trajCompleted:"Completed",trajFailed:"Failed",trajStarted:"Started",trajTokens:"Token usage",trajNoContent:"This record has no displayable content",encodingLossWarning:"This historical tool output was already damaged when saved. Unrecoverable lines are hidden; the current Pi SDK forces new PowerShell output to UTF-8.",ttft:"TTFT",decode:"Decode",inspector:"Record inspector",setGeneral:"General",setModels:"Models",enterBehavior:"Enter while busy",enterBehaviorDesc:"Only while pi is running; Ctrl/Cmd+Enter sends the other way",enterQueue:"Queue: sent after this turn ends",enterSteer:"Steer: delivered after the current tool call",setSkills:"Skills",importSessions:"Import sessions",importDesc:"Losslessly import conversations from Codex / Claude Code / Grok / ZCode / dsh / opencode on this machine into pi sessions: text, thinking, tool calls and results, timestamps and usage are all kept. If the original project directory still exists locally the session lands in that workspace; otherwise it falls back to the workspace selected below. Source data is only read, never modified.",importRescan:"Rescan",importScanning:"Scanning...",importSourceClaude:"Claude Code",importSourceCodex:"Codex",importSourceGrok:"Grok",importSourceZcode:"ZCode",importSourceDsh:"dsh",importSourceOpencode:"opencode",importSourceError:"{source} scan failed: {message}",importGroupCount:"{n} sessions \xb7 {imported} imported",importPickSource:"Choose a source",importLimitHint:"Only the {n} most recent conversations per source are scanned",importLimitHintTooltip:"To see older sessions, raise SCAN_LIMIT_PER_SOURCE in src/lib/session-import/index.ts",importSelectAll:"Select group",importSelectNone:"Clear group",importClearSelection:"Clear",importRun:"Import selected ({n})",importRunning:"Importing...",importFallbackWorkspace:"Fallback workspace",importFallbackHint:"Used when the original project folder is gone",importWhereGoes:"Destination",importGoesOriginal:"Back to its original workspace",importGoesFallback:"Original folder is gone — uses the fallback workspace",importAlready:"Imported",importUntitled:"(untitled)",importNoProject:"(no project directory)",importMessages:"{n} messages",importEmpty:"No importable local sessions found",importReportSummary:"Imported {imported} \xb7 skipped {skipped} \xb7 failed {failed}",drawerPanel:"Drawer",drawerSections:"Drawer sections",drawerPrompts:"Prompts",setPlugins:"Plugins",setRemote:"Remote access",remoteBuiltin:"Built-in plugin",remoteLanTitle:"Local network",remoteLanHint:"Devices on the same Wi-Fi can open the address below; the mobile layout is already applied. On by default.",remotePublicTitle:"Public access",remotePublicHint:"Once on, any browser can open it with nothing to install. Cloudflare assigns a random address that changes on every start.",remoteStart:"Turn on",remoteStop:"Turn off",remoteWorking:"Starting…",remoteRunning:"Running",remoteStopped:"Off",remotePending:"Address created, taking effect…",remoteEngineMissing:"cloudflared not found. Install it and retry, or point PIWEB_CLOUDFLARED at it.",remoteFailed:"Action failed",remoteBlockedAuth:"Remote access is unavailable because authentication is off — it would be an open, password-free entry. Start with the piweb launcher, or set PI_WEB_AUTH=1.",remoteBlockedDev:"Development mode serves this machine only, so remote access is unavailable. Build first, then start in production mode.",remoteSessionsTitle:"Signed-in devices",remoteSessionsHint:"Phones and other computers stay signed in for 30 days. If a device is lost or a link leaked, make every device (including this one) sign in again with the launch token.",remoteSignOutAll:"Sign out all devices",remoteSignOutAllConfirm:"Click again to confirm",appearance:"Appearance",appearanceMode:"Light / Dark",themeLight:"Light",themeDark:"Dark",themeSystem:"System",themeSilverSteel:"Silver & Steel",themeLimestoneCoal:"Limestone & Coal",themeLinenMoss:"Linen & Moss",themeNordPaper:"Nord & Paper",themePebrel:"Pebrel",themeDsh:"Sea & Ink",fontSize:"Font size",fontUiSize:"UI font size",fontUiSizeDesc:"Sidebar, buttons, labels and other UI text",fontChatSize:"Chat font size",fontChatSizeDesc:"Message body, user bubbles and the composer",fontUiFamily:"UI font family",fontUiFamilyDesc:"Font used by the sidebar, buttons, labels and other UI text",fontMonoFamily:"Code font family",fontMonoFamilyDesc:"Monospace font used by code blocks, diffs and inline code",fontCustom:"Custom…",fontCustomPlaceholder:"Font stack, e.g. Fira Code, monospace",language:"Language",openConfigFile:"Open config file",providerAuthOk:"Configured",providerReady:"Request authentication ready",authUnavailable:"Credentials unavailable",credentialSource:"Credential: {source}",authSourceRuntime:"runtime",authSourceEnvironment:"environment",authSourceCommand:"models.json command",authSourceProvider:"provider config",apiKey:"API Key",apiKeyStored:"Saved; leave blank to keep it",providerIdImmutable:"A Provider ID cannot be changed after creation. Delete and recreate it to rename it.",modelConfigReopen:"Model configuration saved and applied. Sessions that are answering pick it up after the current turn.",customModelIdentityNotice:"A custom model ID is only a route name sent to that API endpoint. PiWeb does not automatically download, attach, or identify local Ollama models.",customApiKeyHint:"Leave blank to use auth.json. Keyless local/private services (Ollama etc.) get a placeholder key automatically on save.",modelsTitle:"Models",modelsDesc:"Enter an API key for each provider to use its models.",addProvider:"Add provider",addCustomProvider:"Add custom provider",customProviderTitle:"Custom provider",edit:"Edit",customBadge:"Custom",providerLabel:"Provider",apiType:"API type",modelsList:"Models (one ID per line)",baseUrl:"Base URL",apiAddress:"API address",apiProtocol:"API protocol",apiKeyOptional:"Enter an API key, or leave blank to use environment authentication",customSettings:"Custom settings",providerDefault:"Provider default",selectProvider:"Select provider",searchProviders:"Search provider name or ID",noProviderMatches:"No matching providers",modelCount:"{count} models",providerId:"Provider ID",providerIdHint:"A lowercase identifier that uniquely identifies this provider in requests and derives its credential name.",providerIdInvalid:"Use lowercase letters, numbers, and single hyphen-separated segments only.",providerIdTaken:"This Provider ID already exists.",displayName:"Display name",displayNameOptional:"Display name (optional)",modelCatalog:"Model catalog",discoverModels:"Fetch available models",allowPrivateDiscovery:"Allow local/private",allowPrivateHint:"Check this when the model address points to loopback or a private network (Ollama, LM Studio, one-api gateways) to allow this probe; chat requests are not affected",discoveringModels:"Fetching...",usingDefaultModels:"Using Pi SDK default models \xb7 {count}",customModelsRequired:"Add at least one model ID that can be sent",modelCatalogEmptyBuiltin:"No model overrides. The model selector will continue using Pi SDK's live official catalog.",modelCatalogEmptyCustom:"No models will appear in the selector. Add at least one model ID.",addModel:"Add model",modelId:"Model ID",createProvider:"Create provider",saving:"Saving...",setKey:"Save key",removeKey:"Remove key",removeOAuth:"Remove OAuth",confirmRemoveOAuth:'Remove the OAuth login for "{name}"? You will need to log in again to use it.',confirmRemoveProvider:'Delete provider "{name}" and its configuration?',confirmRemoveKey:'Remove the saved key for "{name}"?',customProviders:"Custom providers (models.json)",toolsSection:"Tools",toolsSectionDesc:"The preset picks the default tools for new sessions; with a session open you can toggle its tools individually (current session only).",toolsCurrentSession:"Current session",toolsActiveCount:"{n}/{total} enabled",toolsNoSession:"Open a session to see and toggle its available tools.",securityToolPreset:"Permission",securityToolPresetDesc:"Switch the current tool set; Workspace Write includes bash and is not a filesystem sandbox",securityTrust:"Project trust",securityTrustDesc:"Auto-trust projects containing .pi/ resources (writes pi settings.json)",trustAsk:"Ask every time",trustAlways:"Always trust",trustNever:"Never trust",versionPiweb:"PiWeb version",versionPiwebDesc:"Version of this web app; click to open the repo",versionPi:"Pi version",versionPiDesc:"Version of the pi agent engine; click to open the repo",checkUpdate:"Check for updates",checkingUpdate:"Checking…",upToDate:"Up to date",updateTo:"Update to {v}",updatingNow:"Updating…",updatedTo:"Updated to {v}; restart PiWeb to apply",updateFailed:"Update failed",updateManualHint:"Stop piweb, then run the command above (Windows cannot replace a running installation)",skillsDesc:"Disabled skills are hidden from the system prompt and only callable via /skill:name",confirmDeleteSkill:'Delete skill "{name}"? Its skill directory will be removed and cannot be recovered.',deleteSkillHint:"Delete the skill directory",skillDeletePackageHint:"package skill: use disable",scopeGlobal:"Global",scopeProject:"Project",scopePackage:"Package",viewSkillFile:"View SKILL.md",packages:"Installed pi packages",packagesEmpty:"No pi packages installed",addPackage:"Install pi package",addPackagePlaceholder:"npm:pkg / git:https://… / local path",installLocal:"Install into current project (-l)",install:"Install",uninstall:"Uninstall",confirmUninstallPackage:'Uninstall "{source}"?',update:"Update",pluginConfig:"Plugin config",pluginList:"Plugin list",pluginPageDesc:"Configure and view installed plugins for this deployment.",searchPlugins:"Search plugins",enabled:"Enabled",disabled:"Disabled",enablePlugin:"Enable",disablePlugin:"Disable",updating:"Updating...",uninstalling:"Uninstalling...",updateSuccess:"Updated successfully",uninstallSuccess:"Uninstalled",extensionsEmpty:"No loaded extensions",extensionLoadError:"Failed to load",resourceDiagnostics:"Resource diagnostics",installing:"Installing…",installSuccess:"Installed and loaded",reloadedSessions:"Reloaded: {loaders} loaders \xb7 {sessions} sessions",projectTrustBanner:"This project has .pi/ extensions or skills; pi loads and runs them only if you trust the project",projectTrustBannerNever:"This project's .pi/ extensions and skills are marked untrusted and will not load",projectTrustAllow:"Trust and load",projectTrustDeny:"Do not trust",projectTrustForget:"Ask again",projectTrustTrusted:"Project trusted",projectTrustUntrusted:"Project not trusted",resources:"carries",toastSaved:"Saved",toastError:"Operation failed",running:"Running",projectPanel:"Project",growthScopeRound:"This round",growthScopeSession:"Session total",growthOnlyChanges:"Changes only",growthPickRound:"Select round",growthRoundJump:"Enter round number...",growthRoundJumpHint:"Type a round number and press Enter to jump",growthPrev:"Previous round",growthNext:"Next round",growthRoundPosition:"Round {current}/{total}",growthRecordNow:'Record now: save the current changes as "Your changes"',growthRecordNone:"No new changes",growthNoRounds:"Nothing recorded yet. Send pi a message and each round's changes will show up here.",growthLoading:"Loading history…",growthNoChangesRound:"No file changes in this round",growthNoSession:"Open or start a session to watch the project grow here.",growthUnavailable:"git was not found on this machine; project growth is unavailable",growthUnavailableFallback:"Growth history is unavailable (no usable git); showing the current directory structure",growthConsentTitle:"Turn on growth history for this workspace?",growthConsentNotGit:"Growth history saves each pi turn's changes as git commits so you can review and compare them. This folder is not a git repository yet; turning it on runs git init here (creates a .git folder).",growthConsentNested:"Growth history saves each pi turn's changes as git commits so you can review and compare them. This folder is inside another repository ({parent}); turning it on creates a nested git repository here, which the outer repository will see as a sub-repository.",growthConsentNote:"Commits live on a private ref (refs/piweb/rounds/…) and never touch your branches or index. The choice is remembered per workspace.",growthConsentAllow:"Turn on and create repository",growthConsentDecline:"Don't record",growthRoundLabel:"Round {n}",growthKindUser:"Your changes",growthRoundFiles:"{n} files",growthJumpToChat:"Show in chat",growthRunning:"Round in progress…",growthStatusAborted:"Aborted",growthStatusError:"Error",growthStatD:"Deleted",growthPending:"Writing…",growthLazyDir:"Current disk entry, not recorded in the selected round",growthTruncated:"Too many changes in this round; showing the first 2000",chatRoundChanged:"This round changed {n} files",chatRoundNoChanges:"No file changes this round",chatRoundShow:"Show this round in the project panel",growthExpandAll:"Expand all",growthCollapseAll:"Collapse all",growthFilter:"Filter…",viewerModeDiff:"Changes",viewerModeContent:"Content",viewerModeRender:"Rendered",viewerFold:"Fold unchanged",viewerUnfold:"Show unchanged",viewerFoldedLines:"\xb7\xb7\xb7 {n} unchanged lines \xb7\xb7\xb7",viewerPrevChange:"Previous change",viewerNextChange:"Next change",viewerFullscreen:"Fullscreen",viewerExitFullscreen:"Exit fullscreen",viewerQuickOpen:"Type a file name to open…",viewerQuickOpenEmpty:"No matching files",viewerNoChanges:"No changes to this file in this scope",viewerDeleted:"This file was deleted in this round; showing its last content",viewerHistorical:"This file is no longer in the current snapshot; showing its last recorded content",viewerMissing:"This file is no longer in the current snapshot or on disk",viewerPatchTruncated:"Diff too large; truncated",viewerCloseTab:"Close tab",viewerNotInSnapshot:"Not in the snapshot (over 1MB or excluded); showing the current content from disk",viewerLoadFailed:"Failed to load",viewerEmpty:"Pick a file from the tree on the left"}},h=(0,e.createContext)({lang:"zh",setLang:()=>{},t:f});function i({children:a}){let[b,c]=(0,e.useState)("zh"),f=(0,e.useCallback)(a=>{c(a),localStorage.setItem("piweb.lang",a)},[]);return(0,d.jsx)(h.Provider,{value:{lang:b,setLang:f,t:g[b]},children:a})}function j(){return(0,e.useContext)(h)}},96487:()=>{}};
|
|
1
|
+
exports.id=496,exports.ids=[496],exports.modules={104:(a,b,c)=>{Promise.resolve().then(c.t.bind(c,81921,23)),Promise.resolve().then(c.t.bind(c,60440,23)),Promise.resolve().then(c.t.bind(c,84342,23)),Promise.resolve().then(c.t.bind(c,82265,23)),Promise.resolve().then(c.t.bind(c,35421,23)),Promise.resolve().then(c.t.bind(c,61335,23)),Promise.resolve().then(c.t.bind(c,70664,23)),Promise.resolve().then(c.bind(c,74661))},1096:(a,b,c)=>{Promise.resolve().then(c.t.bind(c,95547,23))},8e3:(a,b,c)=>{"use strict";c.d(b,{N:()=>e,h:()=>f});var d=c(48249);function e({size:a=18,className:b,style:c}){return(0,d.jsxs)("svg",{width:a,height:a,viewBox:"165.29 165.29 469.43 469.43","aria-hidden":!0,className:b,style:{color:"var(--dsw-label-primary)",display:"block",flex:"none",...c},children:[(0,d.jsx)("path",{fill:"currentColor",fillRule:"evenodd",d:"M165.29 165.29 H517.36 V400 H400 V517.36 H282.65 V634.72 H165.29 Z M282.65 282.65 V400 H400 V282.65 Z"}),(0,d.jsx)("path",{fill:"currentColor",d:"M517.36 400 H634.72 V634.72 H517.36 Z"})]})}function f({compact:a=!1}){return a?(0,d.jsx)(e,{size:18}):(0,d.jsxs)("div",{className:"inline-flex items-center select-none",style:{color:"var(--dsw-label-primary)",gap:6},children:[(0,d.jsx)(e,{size:17}),(0,d.jsx)("span",{className:"inline-flex items-center",style:{fontSize:16.5,fontWeight:600,letterSpacing:"-0.02em",color:"var(--dsw-label-primary)",lineHeight:1},children:"pi"}),(0,d.jsx)("span",{className:"inline-flex items-center justify-center font-bold",style:{fontSize:9.5,letterSpacing:"0.06em",height:15,paddingLeft:4.5,paddingRight:4.5,borderRadius:4,background:"var(--dsw-label-primary)",color:"var(--dsw-bg-base)",lineHeight:1,textTransform:"uppercase"},children:"HARNESS"})]})}},18874:()=>{},23635:()=>{},36552:(a,b,c)=>{Promise.resolve().then(c.t.bind(c,95547,23)),Promise.resolve().then(c.t.bind(c,15098,23)),Promise.resolve().then(c.t.bind(c,47644,23)),Promise.resolve().then(c.t.bind(c,33859,23)),Promise.resolve().then(c.t.bind(c,98099,23)),Promise.resolve().then(c.t.bind(c,16237,23)),Promise.resolve().then(c.t.bind(c,98562,23)),Promise.resolve().then(c.t.bind(c,36675,23))},36593:()=>{},55091:(a,b,c)=>{"use strict";Object.defineProperty(b,"__esModule",{value:!0}),Object.defineProperty(b,"default",{enumerable:!0,get:function(){return f}});let d=c(5735),e=c(22675);function f(){return(0,d.jsx)(e.HTTPAccessErrorFallback,{status:404,message:"This page could not be found."})}("function"==typeof b.default||"object"==typeof b.default&&null!==b.default)&&void 0===b.default.__esModule&&(Object.defineProperty(b.default,"__esModule",{value:!0}),Object.assign(b.default,b),a.exports=b.default)},59645:(a,b,c)=>{"use strict";function d(){return[{type:"image/svg+xml",sizes:"any",url:"/icon.svg?779ce17318f43f72"}]}c.r(b),c.d(b,{default:()=>d})},60587:()=>{},61135:()=>{},76537:(a,b,c)=>{"use strict";c.r(b),c.d(b,{default:()=>g,metadata:()=>e,viewport:()=>f});var d=c(5735);c(18874),c(36593),c(61135);let e={title:"pi",description:"Web UI for the pi coding agent"},f={width:"device-width",initialScale:1,themeColor:[{media:"(prefers-color-scheme: light)",color:"#fcfbf9"},{media:"(prefers-color-scheme: dark)",color:"#2e3440"}]};function g({children:a}){return(0,d.jsx)("html",{lang:"zh-CN",suppressHydrationWarning:!0,children:(0,d.jsx)("body",{suppressHydrationWarning:!0,children:a})})}},78335:()=>{},87944:(a,b,c)=>{Promise.resolve().then(c.t.bind(c,81921,23))},93961:(a,b,c)=>{"use strict";c.d(b,{I18nProvider:()=>i,s:()=>j});var d=c(48249),e=c(67484);let f={confirm:"确认",cancel:"取消",delete:"删除",rename:"重命名",renameSession:"重命名会话",renameWorkspace:"重命名工作区",search:"搜索",save:"保存",close:"关闭",error:"出错",copy:"复制",copyFailed:"复制失败",externalImage:"外部图片,点击加载",chatWidthHandle:"拖动调整对话宽度",editMessage:"编辑这条消息",sendEdit:"重新发送",editMessageFailed:"编辑重发失败",export:"导出",settings:"设置",newChat:"新会话",reconnecting:"连接中断,正在重连…",sessionListLoadFailed:"会话列表加载失败",retry:"重试",compacting:"正在压缩上下文…",compactionComplete:"上下文压缩完成",compactionFailed:"上下文压缩失败",pickWorkspaceFirst:"请先选择工作区",capacityFields:"容量",contextWindowLabel:"上下文窗口",maxTokensLabel:"最大输出",capacityHint:"留空用默认 \xb7 支持 256K / 2M 写法",capacityInvalid:"第 {n} 行:容量需为数字(可用 K/M)",discoverEmpty:"远端没有返回可识别的模型",candidateTitle:"发现 {count} 个模型,勾选要添加的",candidateAll:"全选",candidatePicked:"已选 {n} 个",candidateAdopt:"添加 {n} 个",runningTool:"Running {name}…",thinkingLive:"Thinking",stepRunning:"Running",stepRan:"已运行",stepRead:"读取",stepSearched:"搜索",stepEdited:"编辑了",stepWrote:"写入了",resultRead:"读取了 {n} 行",resultFound:"找到 {n} 处",resultWrote:"{n} 行",sumThought:"思考了 {d}",sumRan:"运行了 {n} 条命令",sumRan1:"运行了 {n} 条命令",sumRead:"读了 {n} 个文件",sumRead1:"读了 {n} 个文件",sumSearched:"搜索了 {n} 次",sumSearched1:"搜索了 {n} 次",sumJoin:",",toolLines:"{n} 行",toolMatches:"{n} 个匹配",toolExit:"退出码 {code}",toolWritten:"已写入",diffSummary:"+{add} −{del} 行",deletedFile:"已删除 {path}",backToBottom:"回到底部",modeSteer:"插话",modeQueue:"排队",sendSteer:"插话:当前工具跑完就送达",sendQueue:"排队:本轮结束后发送",queueEdit:"↑ 取回编辑",queueDrop:"丢弃",viewInTrajectory:"在轨迹中查看",turnRanFor:"耗时 {duration}",durationSeconds:"{seconds} 秒",durationMinutes:"{minutes} 分 {seconds} 秒",clockMd:"{m}月{d}日",clockYmd:"{y}年{m}月{d}日",turnUsageTitle:"本回合用量",filesPanel:"文件",outline:"大纲",moreActions:"更多",filesFilter:"筛选文件…",filesShowAll:"显示 node_modules 等",filesHideNoise:"隐藏 node_modules 等",fileReference:"引用到输入框",fileOpenEditor:"在编辑器中打开",fileChangedByPi:"本会话中被 pi 修改",fileRenderMarkdown:"渲染",fileRawSource:"源码",gitUnavailable:"未找到 git 命令,请确认已安装并加入 PATH。",gitUpstream:"上游 {name}",gitNoUpstream:"无上游分支",gitConflict:"冲突",gitAskCommit:"让 pi 提交",gitDetails:"Git 详情",gitAskCommitPrompt:"请检查当前工作区的变更,把相关改动分组提交,写清晰的 commit message。",gitDiffEmpty:"没有差异",gitDiffTruncated:"差异过长,已截断",gitBinary:"二进制文件,不显示差异",gitStagedDiff:"暂存区差异",gitWorktreeDiff:"工作区差异",gitNoCommits:"尚无提交",gitBack:"返回",gitPanel:"Git",panelRefresh:"刷新",panelLoading:"加载中…",filesEmpty:"空目录",filesBack:"返回",fileBinary:"二进制文件,不提供预览",filePreviewTruncated:"文件较大,仅显示前 256 KB",entriesTruncated:"目录条目过多,仅显示前 2000 项",gitNotRepo:"此工作区不是 Git 仓库。",gitDetached:"分离头指针",gitAhead:"领先 {n}",gitBehind:"落后 {n}",gitStaged:"已暂存",gitUnstaged:"未暂存",gitUntracked:"未跟踪",gitNoChanges:"工作区干净,没有变更",gitStatusUnknown:"Git 状态读取失败,无法确认是否有变更",gitRecentCommits:"最近提交",toolNoOutput:"无输出",toolFailed:"失败",thinkingClamped:"当前模型不支持「{requested}」,已改为「{level}」",modelError:"模型返回错误",modelErrorTimes:"连续 {n} 次",modelErrorRateLimit:"限流:请求过于频繁,稍等片刻再试",modelErrorBilling:"余额或配额不足",modelErrorAuth:"鉴权失败:检查该供应商的 API Key",modelErrorNotFound:"模型不存在或当前 Key 无权访问",modelErrorContext:"上下文超出模型窗口,可用 /compact 压缩后重试",modelErrorTimeout:"请求超时",modelErrorServer:"供应商服务端出错或过载",modelErrorModeration:"请求内容被供应商审核拦截(敏感词),换措辞或新开会话试试",modelErrorNetwork:"网络连接失败",turnAborted:"已中止",moreLines:"还有 {n} 行",commandLines:"{n} 行脚本",thinkLabel:"思考",expandOutput:"展开全部输出",expandDiff:"展开改动",collapseOutput:"收起",workspaces:"工作区",pickFolderTitle:"选择工作区文件夹",pickFolderUp:"上一级",pickFolderConfirm:"选择此文件夹",pickFolderEmpty:"此目录下没有子文件夹",pickFolderTruncated:"只列出前 {n} 个文件夹",pickFolderLoading:"读取中…",searchSessions:"搜索会话...",addWorkspace:"添加工作区",groupBy:"分组方式",sortBy:"排序方式",byWorkspace:"按工作区",flatList:"单列表",manualOrder:"按创建时间",recentUpdated:"最近更新",newSessionHere:"在此工作区新会话",removeWorkspace:"从列表移除",deleteWorkspace:"删除工作区",deleteWorkspaceConfirm:"将把“{name}”从工作区列表中移除。文件夹与会话记录会保留,其会话将显示在“未分组”下。",deleteWorkspacePending:"正在删除工作区…",workspaceNameConflict:"已存在名为“{name}”的工作区。",ungrouped:"未分组",forkSession:"在新对话中分支",archiveSession:"归档会话",unarchiveSession:"取消归档",archivedSessions:"已归档",deleteAllSessions:"删除全部会话",deleteAllConfirm:"删除此工作区的全部会话?不可恢复。",contextInject:"上下文注入",autoCompact:"自动压缩",settingsLoading:"正在读取设置…",settingsLoadFailed:"设置读取失败;未显示默认值。请重试。",settingsSaveFailed:"设置未保存,请检查输入或网络后重试。",settingsRetry:"重试",autoCompactDesc:"上下文超出阈值时自动压缩历史",reserveTokens:"保留 Token",keepRecentTokens:"近期保留",autoRetry:"自动重试",autoRetryDesc:"请求失败后的自动重试",maxRetries:"最大重试次数",baseDelayMs:"初始延迟 (ms)",reloadExtensions:"重载全部扩展",cycleModel:"循环切换模型",cycleModelHint:"循环模型(Shift 点击切换到前一个)",branches:"分支",noBranches:"暂无可跳转的分支节点",oauthLogin:"OAuth 登录",authMethod:"认证方式",webAuth:"访问认证",webAuthTokenOn:"已启用(启动令牌)",loginTokenTitle:"这个实例用启动令牌登录",loginTokenDesc:"请打开启动 PiWeb 时终端里打印的登录链接(形如 …/?token=…),或在已登录的电脑上打开 设置 → 远程连接,复制带令牌的地址。令牌每次重启都会更换;打开一次后浏览器会记住 30 天。",logout:"退出登录",authMethodApiKey:"API 密钥",oauthDevicePrompt:"请在浏览器中完成授权",oauthOpenAuth:"打开授权页面",oauthDeviceCode:"设备码",oauthCodeCopied:"已复制",usageQuotaLabel:"API 配额",usageRequests:"请求",usageRefresh:"刷新配额",usageProbe:"检测配额",usageProbing:"检测中…",usageProbeDisclosure:"检测会向 xAI 发送一次可能计费的最小请求。",usageProbeFailed:"配额检测失败,未获得用量信息。",usagePlan:"套餐",usageQuotaRemaining:"额度剩余",queryingQuota:"正在查询额度…",usageReadOnlyDisclosure:"读取提供商的只读用量端点,不消耗额度。",usageReset:"刷新时间",usageWindowWeekly:"周限",usageWindowMonthly:"月限",usageWindowHours:"{n} 小时",usageWindowDays:"{n} 天",usageWindowRolling:"滚动窗口",usageWindowChat:"对话",usageWindowCompletions:"补全",usageWindowPremium:"高级请求",usageVariantOpus:"Opus",usageVariantCode:"代码",usageBalanceGranted:"赠金",usageBalanceToppedUp:"充值",usageBalanceVoucher:"代金券",usageBalanceCash:"现金",usageBalanceUsed:"已用",usageBalanceLimit:"上限",oauthWait:"等待授权…",oauthCancel:"取消登录",noSessions:"暂无会话",startWith:"新建工作区",inputPlaceholder:"给 pi 发消息…",thinking:"思考",thinkingOff:"关闭",model:"模型",selectModel:"选择模型",triggerLoading:"正在加载模型…",blockedComposer:"当前模型不可用,请先选择模型",emptyModels:"没有可用的模型。",emptyEfforts:"当前模型未提供推理等级。",thinkingUnsupported:"此模型不支持",thinkingUnsupportedHint:'模型没有声明推理能力。自定义模型请在 ~/.pi/agent/models.json 里给该模型加 "reasoning": true(可选 thinkingLevelMap 指定档位)',toolReadonly:"Read Only",toolStandard:"Workspace Write",toolFull:"Full access",stop:"停止",send:"发送",imageAttachment:"图片附件",imageTooLarge:"单张图片不能超过 20 MB",imageCountLimit:"一次最多添加 20 张图片",imageTypeUnsupported:"仅支持 JPEG、PNG、WebP 和 GIF 图片",dropToAttach:"松开添加附件",dropToAttachHint:"图片直接附到消息;其他文件(压缩包/文档等)保存后以路径引用,模型可用工具读取",dropLimits:"图片 ≤ 20MB \xb7 最多 20 张 \xb7 其他文件 ≤ 100MB \xb7 最多 16 个",uploading:"正在上传…",uploadFailed:"上传失败",uploadTooLarge:"单个文件不能超过 100 MB",uploadCountLimit:"一次最多添加 16 个文件",attachmentLine:"附件:{path}({size})",cmdMenu:"命令",slashCatalog:"命令与技能",skillType:"技能",cmdCompact:"压缩更早的对话历史",cmdExport:"下载本会话日志",cmdModel:"选择本会话使用的模型",cmdNew:"新建会话",cmdFork:"分叉会话",cmdReload:"重载扩展、技能与提示模板(pi /reload)",promptType:"模板",extensionCmdType:"扩展",cmdUnknown:"没有这个命令:/{name}。可用命令见输入框的 / 菜单",extensionDialogTag:"扩展",extensionStatus:"扩展状态",contextUsed:"上下文已用",contextUnknown:"上下文用量未知",contextSystem:"系统提示词",contextMessages:"对话消息",contextTools:"工具",promptPanel:"提示词来源",promptRefresh:"刷新",promptLoading:"加载中…",promptColdHint:"会话尚未启动:先列出磁盘上的提示词文件;打开会话后才会出现「组装后的系统提示词」与工具定义。",promptOriginProject:"项目",promptOriginAgent:"个人",promptOriginPackage:"包",promptOriginExtension:"扩展",promptKindSystem:"系统提示词文件",promptKindAppend:"追加提示词",promptKindAgents:"项目记忆(AGENTS.md)",promptKindSkill:"技能提示词",promptKindTemplate:"提示模板",promptKindTool:"工具提示词",promptKindAssembled:"系统提示词",promptKindCompacted:"压缩摘要",promptCompactedKey:"进入上下文的压缩摘要",promptGuidelines:"提示词指南",promptParameters:"参数定义",promptAssembledKey:"当前生效的系统提示词",promptToolBuiltin:"内置",promptToolExtension:"扩展",contextSystemPrompt:"System Prompt",contextSystemTools:"System Tools",contextCustomTools:"Custom Tools",contextMemory:"Memory(AGENTS.md)",contextSkills:"Skills",contextUserMessages:"User Messages",contextAgentText:"Agent Text",contextAgentThinking:"Agent Thinking",contextAgentToolCall:"Agent Tool Call",contextToolOutput:"Tool Output",contextCompacted:"Compacted Data",contextAutoCompactBuffer:"Auto-Compact Buffer",contextFreeSpace:"Free Space",turns:"轮次",toolCalls:"工具调用",cost:"花费",duration:"耗时",cacheHits:"缓存命中",statsCounts:"{turns} 轮 \xb7 {steps} 步",ttftAverage:"首 token 平均",inputTokens:"输入",outputTokens:"输出",tabChat:"对话",tabTrajectory:"轨迹",sessionLog:"Session log",sessionDetails:"会话详情",exportJsonl:"导出 JSONL",trajTimeline:"时间轴",trajModeSeq:"等距",trajModeTime:"时间",trajModeDur:"间隔",trajEmpty:"本会话还没有轨迹记录",trajSearchPlaceholder:"搜索轨迹",trajNoMatch:"没有匹配的轨迹记录",trajInput:"输入",trajModel:"模型",trajTools:"工具",trajOutput:"输出",trajThink:"思考",trajTime:"时间",trajTurn:"轮次",trajSystem:"系统",trajSession:"会话",trajSummary:"摘要",trajPreview:"预览",trajRaw:"原始",trajSource:"来源",trajStatus:"状态",trajCompleted:"已完成",trajFailed:"失败",trajStarted:"开始时间",trajTokens:"Token 用量",trajNoContent:"此记录没有可显示的内容",encodingLossWarning:"这段历史工具输出在写入时已经损坏,无法恢复的行已隐藏。当前 Pi SDK 已对新的 PowerShell 输出强制使用 UTF-8。",ttft:"首 token",decode:"解码",inspector:"记录详情",setGeneral:"通用设置",setModels:"模型",enterBehavior:"繁忙时 Enter 键行为",enterBehaviorDesc:"仅在 pi 运行时生效;Ctrl/Cmd+Enter 用另一种方式发送",enterQueue:"排队:本轮结束后发送",enterSteer:"插话:当前工具跑完就送达",setSkills:"技能",importSessions:"导入会话",importDesc:"把本机 Codex / Claude Code / Grok / ZCode / dsh / opencode 的对话无损导入成 pi 会话:文本、思考、工具调用与结果、时间戳、用量都保留。源项目目录还在本机就导回原工作区,否则落到下面选的兜底工作区。只读源数据,不修改源工具的任何文件。",importRescan:"重新扫描",importScanning:"扫描中…",importSourceClaude:"Claude Code",importSourceCodex:"Codex",importSourceGrok:"Grok",importSourceZcode:"ZCode",importSourceDsh:"dsh",importSourceOpencode:"opencode",importSourceError:"{source} 扫描失败:{message}",importGroupCount:"{n} 条 \xb7 已导入 {imported}",importPickSource:"选择来源",importLimitHint:"每个来源只列最近 {n} 条对话(更早的会话不扫描,省时省资源)",importLimitHintTooltip:"看更早的会话:把 src/lib/session-import/index.ts 里的 SCAN_LIMIT_PER_SOURCE 调大",importSelectAll:"全选本组",importSelectNone:"清空本组",importClearSelection:"清空选择",importRun:"导入所选 ({n})",importRunning:"导入中…",importFallbackWorkspace:"兜底工作区",importFallbackHint:"原项目目录已不在本机时落到这里",importWhereGoes:"导入去向",importGoesOriginal:"回到原工作区",importGoesFallback:"原目录已不在,用兜底工作区",importAlready:"已导入",importUntitled:"(无标题)",importNoProject:"(无项目目录)",importMessages:"{n} 条消息",importEmpty:"没有找到可导入的本地会话",importReportSummary:"成功 {imported} \xb7 跳过 {skipped} \xb7 失败 {failed}",drawerPanel:"右侧抽屉",drawerSections:"抽屉入口",drawerPrompts:"提示词",setPlugins:"插件",setRemote:"远程连接",remoteBuiltin:"内置插件",remoteLanTitle:"局域网入口",remoteLanHint:"同一个 WiFi 下的设备直接打开下面地址即可,手机排版已适配。默认开启。链接带登录令牌:点「复制」发到手机,打开就直接登录;令牌即凭据,别发给别人。",remotePublicTitle:"公网入口",remotePublicHint:"开启后任何浏览器都能打开,无需安装客户端。地址由 Cloudflare 随机分配,每次启动都会变。链接同样带登录令牌。",remoteLinkCopied:"已复制(含令牌)",remoteStart:"开启远程连接",remoteStop:"关闭",remoteWorking:"启动中…",remoteRunning:"运行中",remoteStopped:"未开启",remotePending:"地址已生成,生效中…",remoteEngineMissing:"找不到 cloudflared。请安装后重试,或用 PIWEB_CLOUDFLARED 指定它的路径。",remoteFailed:"操作失败",remoteBlockedAuth:"认证没开,远程连接不可用:开出去就是一个免密入口。请用 piweb 启动器启动,或设 PI_WEB_AUTH=1。",remoteBlockedDev:"开发模式只服务本机,远程连接不可用。请先构建,再用生产模式启动。",remoteSessionsTitle:"已登录的设备",remoteSessionsHint:"手机、别的电脑登录后一直有效(30 天)。设备丢了或链接被别人拿到时,可以让所有设备(包括这台)都要重新用启动令牌登录。",remoteSignOutAll:"让所有设备重新登录",remoteSignOutAllConfirm:"再点一次确认",appearance:"外观",appearanceMode:"亮暗模式",themeLight:"浅色",themeDark:"深色",themeSystem:"跟随系统",themeSilverSteel:"银钢",themeLimestoneCoal:"石灰与煤炭",themeLinenMoss:"亚麻与苔绿",themeNordPaper:"北欧纸墨",themePebrel:"Pebrel",themeDsh:"海与墨",fontSize:"正文字号",fontUiSize:"界面字体",fontUiSizeDesc:"侧栏、按钮、标签等界面文字",fontChatSize:"对话字体",fontChatSizeDesc:"消息正文、用户气泡与输入框",fontUiFamily:"界面字体族",fontUiFamilyDesc:"侧栏、按钮、标签等界面文字使用的字体",fontMonoFamily:"代码字体族",fontMonoFamilyDesc:"代码块、diff、行内代码使用的等宽字体",fontCustom:"自定义…",fontCustomPlaceholder:"输入字体栈,如 Fira Code, monospace",language:"界面语言",openConfigFile:"打开配置文件",providerAuthOk:"已配置",providerReady:"请求认证可用",authUnavailable:"凭据不可用",credentialSource:"凭据:{source}",authSourceRuntime:"运行时",authSourceEnvironment:"环境变量",authSourceCommand:"models.json 命令",authSourceProvider:"Provider 配置",apiKey:"API Key",apiKeyStored:"已保存;留空保持不变",providerIdImmutable:"Provider ID 创建后不可修改;如需更名,请删除后重建。",modelConfigReopen:"模型配置已保存并立即生效;正在回答的会话在本轮结束后生效。",customModelIdentityNotice:"自定义模型 ID 只是发往该 API 地址的路由名;PiWeb 不会自动下载、接入或识别本机 Ollama 模型。",customApiKeyHint:"可留空改用 auth.json;指向本机/私网的无鉴权服务(Ollama 等)保存时自动填占位值。",modelsTitle:"模型",modelsDesc:"填入各提供方的 API 密钥即可使用其模型。",addProvider:"添加提供方",addCustomProvider:"添加自定义提供方",customProviderTitle:"自定义提供方",edit:"编辑",customBadge:"自定义",providerLabel:"提供方",apiType:"API 类型",modelsList:"模型(每行一个 ID)",baseUrl:"Base URL",apiAddress:"API 地址",apiProtocol:"API 协议",apiKeyOptional:"输入 API 密钥,或留空使用环境认证",customSettings:"自定义设置",providerDefault:"提供方默认",selectProvider:"选择提供方",searchProviders:"搜索提供方名称或 ID",noProviderMatches:"没有匹配的提供方",modelCount:"{count} 个模型",providerId:"Provider ID",providerIdHint:"以小写字母开头的标识,在请求中唯一标识该提供方,并用于派生凭据名。",providerIdInvalid:"只能使用小写字母、数字和单个连字符分段。",providerIdTaken:"该 Provider ID 已存在。",displayName:"显示名称",displayNameOptional:"显示名称(可选)",modelCatalog:"模型目录",discoverModels:"获取可用模型",allowPrivateDiscovery:"允许本机/私网",allowPrivateHint:"模型地址指向本机或私有网络(如 Ollama、LM Studio、one-api 本地网关)时勾选,本次探测放行;发消息不受此限制",discoveringModels:"获取中...",usingDefaultModels:"正在使用 Pi SDK 默认模型 \xb7 {count} 个",customModelsRequired:"至少添加一个可发送的模型 ID",modelCatalogEmptyBuiltin:"未添加覆盖模型;模型选择器会继续实时使用 Pi SDK 的官方模型目录。",modelCatalogEmptyCustom:"模型选择器中将不显示任何模型;请至少添加一个模型 ID。",addModel:"添加模型",modelId:"模型 ID",createProvider:"创建提供方",saving:"保存中...",setKey:"保存 Key",removeKey:"移除 Key",removeOAuth:"移除 OAuth",confirmRemoveOAuth:"确定移除“{name}”的 OAuth 登录吗?移除后需重新登录才能使用。",confirmRemoveProvider:"确定删除提供方“{name}”及其配置吗?",confirmRemoveKey:"确定移除“{name}”的已保存密钥吗?",customProviders:"自定义 Provider(models.json)",toolsSection:"工具启用情况",toolsSectionDesc:"三档预设决定新会话的默认工具;打开会话后可逐个启停当前会话的工具(仅本会话生效)。",toolsCurrentSession:"当前会话",toolsActiveCount:"{n}/{total} 已启用",toolsNoSession:"打开一个会话后,这里会显示可用工具并支持逐个启停。",securityToolPreset:"权限",securityToolPresetDesc:"切换当前会话工具集;Workspace Write 包含 bash,并非文件系统沙箱",securityTrust:"项目信任",securityTrustDesc:"首次进入含 .pi/ 资源的项目时是否自动信任(写入 pi settings.json)",trustAsk:"每次询问",trustAlways:"总是信任",trustNever:"从不信任",versionPiweb:"PiWeb 版本",versionPiwebDesc:"本 Web 应用的版本,点击打开仓库",versionPi:"Pi 版本",versionPiDesc:"pi 智能体内核的版本,点击打开仓库",checkUpdate:"检查更新",checkingUpdate:"检查中…",upToDate:"已是最新",updateTo:"更新到 {v}",updatingNow:"更新中…",updatedTo:"已更新到 {v},重启 PiWeb 后生效",updateFailed:"更新失败",updateManualHint:"先停止 piweb,再执行上面的命令(Windows 无法替换运行中的安装目录)",skillsDesc:"关闭后技能不会出现在系统提示中,仅可通过 /skill:名称 手动调用",confirmDeleteSkill:"确定删除技能“{name}”吗?将删除其所在技能目录,不可恢复。",deleteSkillHint:"删除技能目录",skillDeletePackageHint:"包技能请用禁用管理",scopeGlobal:"全局",scopeProject:"项目",scopePackage:"包",viewSkillFile:"查看 SKILL.md",packages:"已安装的 pi 包",packagesEmpty:"尚未安装任何 pi 包",addPackage:"安装 pi 包",addPackagePlaceholder:"npm:包名 / git:https://… / 本地路径",installLocal:"安装到当前项目(-l)",install:"安装",uninstall:"卸载",confirmUninstallPackage:"确定卸载“{source}”吗?",update:"更新",pluginConfig:"插件配置",pluginList:"插件列表",pluginPageDesc:"配置和查看本部署已安装的插件。",searchPlugins:"搜索插件",enabled:"已启用",disabled:"已停用",enablePlugin:"启用",disablePlugin:"停用",updating:"正在更新...",uninstalling:"正在卸载...",updateSuccess:"更新成功",uninstallSuccess:"已卸载",extensionsEmpty:"没有已加载的扩展",extensionLoadError:"加载失败",resourceDiagnostics:"资源诊断",installing:"正在安装…",installSuccess:"已安装并加载",reloadedSessions:"已重载:{loaders} 个加载器 \xb7 {sessions} 个会话",projectTrustBanner:"此项目含 .pi/ 扩展或技能,pi 需要你的信任才会加载并执行它们",projectTrustBannerNever:"此项目的 .pi/ 扩展与技能已被设为不信任,不会加载",projectTrustAllow:"信任并加载",projectTrustDeny:"不信任",projectTrustForget:"重新询问",projectTrustTrusted:"项目已信任",projectTrustUntrusted:"项目未信任",resources:"携带",toastSaved:"已保存",toastError:"操作失败",running:"运行中",projectPanel:"项目",growthScopeRound:"本轮",growthScopeSession:"本会话累计",growthOnlyChanges:"只看改动",growthPickRound:"选择轮次",growthRoundJump:"输入轮号...",growthRoundJumpHint:"输入轮号后按回车跳到该轮",growthPrev:"上一轮",growthNext:"下一轮",growthRoundPosition:"第 {current}/{total} 轮",growthRecordNow:"立即记录:把当前改动记为「你的修改」",growthRecordNone:"没有新的改动",growthNoRounds:"还没有记录。发一条消息让 pi 开始工作,每一轮的改动会出现在这里。",growthLoading:"正在读取记录…",growthNoChangesRound:"本轮无文件改动",growthNoSession:"打开或新建一个会话后,这里会显示项目的生长过程。",growthUnavailable:"机器上找不到 git,项目生长功能不可用",growthUnavailableFallback:"生长记录不可用(找不到可用的 git),已显示当前目录结构",growthConsentTitle:"要为这个工作区开启生长记录吗?",growthConsentNotGit:"生长记录会把 pi 每一轮的改动存成 git 提交,方便回看和对比。这个目录还不是 git 仓库,开启后会在这里执行 git init(新建 .git 目录)。",growthConsentNested:"生长记录会把 pi 每一轮的改动存成 git 提交,方便回看和对比。这个目录是另一个仓库({parent})的子目录,开启后会在这里再建一个嵌套的 git 仓库,外层仓库会把它当成一个子仓库看待。",growthConsentNote:"记录挂在专用引用 refs/piweb/rounds/… 上,不动分支和暂存区。选择会按工作区记住。",growthConsentAllow:"开启并建仓库",growthConsentDecline:"不记录",growthRoundLabel:"第 {n} 轮",growthKindUser:"你的修改",growthRoundFiles:"{n} 个文件",growthJumpToChat:"在对话里看",growthRunning:"本轮进行中…",growthStatusAborted:"已中止",growthStatusError:"出错",growthStatD:"删除",growthPending:"生成中",growthLazyDir:"当前磁盘条目,不在所选这一轮的记录中",growthTruncated:"这一轮变更过多,只显示前 2000 条",chatRoundChanged:"本轮改了 {n} 个文件",chatRoundNoChanges:"本轮没有改动文件",chatRoundShow:"在项目栏里查看这一轮",growthExpandAll:"展开全部",growthCollapseAll:"收起全部",growthFilter:"筛选…",viewerModeDiff:"变更",viewerModeContent:"内容",viewerModeRender:"渲染",viewerFold:"折叠未改动",viewerUnfold:"展开未改动",viewerFoldedLines:"\xb7\xb7\xb7 {n} 行未改动 \xb7\xb7\xb7",viewerPrevChange:"上一处改动",viewerNextChange:"下一处改动",viewerFullscreen:"全屏",viewerExitFullscreen:"退出全屏",viewerQuickOpen:"输入文件名打开…",viewerQuickOpenEmpty:"没有匹配的文件",viewerNoChanges:"这一范围内此文件没有变化",viewerDeleted:"此文件在本轮被删除,显示的是删除前的内容",viewerHistorical:"此文件已不在当前快照中,显示最近一次记录的内容",viewerMissing:"此文件已不在当前快照或磁盘中",viewerPatchTruncated:"差异过大,已截断",viewerCloseTab:"关闭页签",viewerNotInSnapshot:"此文件不在快照里(超过 1MB 或被排除),显示磁盘上的当前内容",viewerLoadFailed:"加载失败",viewerEmpty:"从左侧树里选择一个文件"},g={zh:f,en:{confirm:"Confirm",cancel:"Cancel",delete:"Delete",rename:"Rename",renameSession:"Rename session",renameWorkspace:"Rename workspace",search:"Search",save:"Save",close:"Close",error:"Error",copy:"Copy",copyFailed:"Copy failed",externalImage:"External image — click to load",chatWidthHandle:"Drag to resize the conversation",editMessage:"Edit this message",sendEdit:"Send again",editMessageFailed:"Edit and resend failed",export:"Export",settings:"Settings",newChat:"New session",reconnecting:"Connection lost, reconnecting…",sessionListLoadFailed:"Failed to load sessions",retry:"Retry",compacting:"Compacting context…",compactionComplete:"Context compaction complete",compactionFailed:"Context compaction failed",pickWorkspaceFirst:"Select a workspace first",capacityFields:"Capacities",contextWindowLabel:"Context window",maxTokensLabel:"Max output",capacityHint:"blank = default \xb7 256K / 2M accepted",capacityInvalid:"Row {n}: capacity must be a number (K/M ok)",discoverEmpty:"No recognizable models returned",candidateTitle:"Found {count} models — pick ones to add",candidateAll:"Select all",candidatePicked:"{n} selected",candidateAdopt:"Add {n}",runningTool:"Running {name}…",thinkingLive:"Thinking",stepRunning:"Running",stepRan:"Ran",stepRead:"Read",stepSearched:"Searched",stepEdited:"Edited",stepWrote:"Wrote",resultRead:"Read {n} lines",resultFound:"Found {n} matches",resultWrote:"{n} lines",sumThought:"Thought for {d}",sumRan:"ran {n} shell commands",sumRan1:"ran {n} shell command",sumRead:"read {n} files",sumRead1:"read {n} file",sumSearched:"searched {n} times",sumSearched1:"searched once",sumJoin:", ",toolLines:"{n} lines",toolMatches:"{n} matches",toolExit:"exit {code}",toolWritten:"written",diffSummary:"+{add} −{del} lines",deletedFile:"deleted {path}",backToBottom:"Back to bottom",modeSteer:"steer",modeQueue:"queue",sendSteer:"Steer: delivered after the current tool call",sendQueue:"Queue: sent after this turn ends",queueEdit:"↑ Edit queued",queueDrop:"Discard",viewInTrajectory:"View in trajectory",turnRanFor:"ran for {duration}",durationSeconds:"{seconds}s",durationMinutes:"{minutes}m {seconds}s",clockMd:"{m}/{d}",clockYmd:"{y}/{m}/{d}",turnUsageTitle:"Turn usage",filesPanel:"Files",outline:"Outline",moreActions:"More",filesFilter:"Filter files…",filesShowAll:"Show node_modules etc.",filesHideNoise:"Hide node_modules etc.",fileReference:"Reference in composer",fileOpenEditor:"Open in editor",fileChangedByPi:"Modified by pi in this session",fileRenderMarkdown:"Render",fileRawSource:"Source",gitUnavailable:"git command not found. Install it and make sure it is on PATH.",gitUpstream:"upstream {name}",gitNoUpstream:"no upstream",gitConflict:"Conflicts",gitAskCommit:"Ask pi to commit",gitDetails:"Git details",gitAskCommitPrompt:"Review the current changes, group related edits into commits, and write clear commit messages.",gitDiffEmpty:"No differences",gitDiffTruncated:"Diff truncated",gitBinary:"Binary file, no diff shown",gitStagedDiff:"Staged diff",gitWorktreeDiff:"Working tree diff",gitNoCommits:"No commits yet",gitBack:"Back",gitPanel:"Git",panelRefresh:"Refresh",panelLoading:"Loading…",filesEmpty:"Empty directory",filesBack:"Back",fileBinary:"Binary file, no preview",filePreviewTruncated:"Large file, showing first 256 KB only",entriesTruncated:"Too many entries, showing first 2000",gitNotRepo:"This workspace is not a Git repository.",gitDetached:"detached HEAD",gitAhead:"ahead {n}",gitBehind:"behind {n}",gitStaged:"Staged",gitUnstaged:"Unstaged",gitUntracked:"Untracked",gitNoChanges:"Working tree clean",gitStatusUnknown:"Git status unavailable; changes could not be determined",gitRecentCommits:"Recent commits",toolNoOutput:"no output",toolFailed:"failed",thinkingClamped:'This model does not support "{requested}"; using "{level}" instead',modelError:"Model returned an error",modelErrorTimes:"{n} times in a row",modelErrorRateLimit:"Rate limited: too many requests, wait a moment and retry",modelErrorBilling:"Insufficient balance or quota",modelErrorAuth:"Authentication failed: check this provider's API key",modelErrorNotFound:"Model not found or not accessible with this key",modelErrorContext:"Context exceeds the model window; try /compact and retry",modelErrorTimeout:"Request timed out",modelErrorServer:"Provider server error or overloaded",modelErrorModeration:"Request blocked by the provider's content filter (sensitive words); rephrase or start a new session",modelErrorNetwork:"Network connection failed",turnAborted:"Aborted",moreLines:"{n} more lines",commandLines:"{n}-line script",thinkLabel:"Thought",expandOutput:"Show full output",expandDiff:"Show changes",collapseOutput:"Collapse",workspaces:"Workspaces",pickFolderTitle:"Choose a workspace folder",pickFolderUp:"Parent folder",pickFolderConfirm:"Use this folder",pickFolderEmpty:"No subfolders here",pickFolderTruncated:"Showing the first {n} folders",pickFolderLoading:"Loading…",searchSessions:"Search sessions...",addWorkspace:"Add workspace",groupBy:"Group by",sortBy:"Sort by",byWorkspace:"Workspace",flatList:"Flat list",manualOrder:"Created",recentUpdated:"Recently updated",newSessionHere:"New session here",removeWorkspace:"Remove from list",deleteWorkspace:"Delete workspace",deleteWorkspaceConfirm:'Remove "{name}" from the workspace list. Folders and session records will be retained, and its sessions will be displayed under "Ungrouped".',deleteWorkspacePending:"Deleting workspace...",workspaceNameConflict:'A workspace named "{name}" already exists.',ungrouped:"Ungrouped",forkSession:"Fork session",archiveSession:"Archive session",unarchiveSession:"Unarchive",archivedSessions:"Archived",deleteAllSessions:"Delete all sessions",deleteAllConfirm:"Delete ALL sessions in this workspace? This cannot be undone.",contextInject:"Context",autoCompact:"Auto compaction",settingsLoading:"Loading settings…",settingsLoadFailed:"Settings could not be loaded. Defaults are not shown; please retry.",settingsSaveFailed:"Settings were not saved. Check the value or connection and retry.",settingsRetry:"Retry",autoCompactDesc:"Automatically compact history when context exceeds the threshold",reserveTokens:"Reserve tokens",keepRecentTokens:"Keep recent",autoRetry:"Auto retry",autoRetryDesc:"Automatically retry failed requests",maxRetries:"Max retries",baseDelayMs:"Initial delay (ms)",reloadExtensions:"Reload all extensions",cycleModel:"Cycle model",cycleModelHint:"Cycle model (Shift-click for previous)",branches:"Branches",noBranches:"No branch points available",oauthLogin:"OAuth login",authMethod:"Authentication",webAuth:"Access authentication",webAuthTokenOn:"Enabled (launch token)",loginTokenTitle:"This instance signs in with a launch token",loginTokenDesc:"Open the login link printed in the terminal when PiWeb started (…/?token=…), or copy a link from Settings → Remote access on a signed-in computer. The token changes on every restart; once opened, the browser remembers it for 30 days.",logout:"Sign out",authMethodApiKey:"API key",oauthDevicePrompt:"Finish authorization in your browser",oauthOpenAuth:"Open authorization page",oauthDeviceCode:"Device code",oauthCodeCopied:"Copied",usageQuotaLabel:"API quota",usageRequests:"Requests",usageRefresh:"Refresh quota",usageProbe:"Check quota",usageProbing:"Checking…",usageProbeDisclosure:"Checking sends one minimal request to xAI that may be billed.",usageProbeFailed:"Quota check failed; no usage data was returned.",usagePlan:"Plan",usageQuotaRemaining:"Remaining quota",queryingQuota:"Querying quota…",usageReadOnlyDisclosure:"Reads the provider's read-only usage endpoint; consumes no quota.",usageReset:"Resets",usageWindowWeekly:"Weekly",usageWindowMonthly:"Monthly",usageWindowHours:"{n}h",usageWindowDays:"{n}d",usageWindowRolling:"Rolling",usageWindowChat:"Chat",usageWindowCompletions:"Completions",usageWindowPremium:"Premium requests",usageVariantOpus:"Opus",usageVariantCode:"Code",usageBalanceGranted:"Granted",usageBalanceToppedUp:"Topped up",usageBalanceVoucher:"Voucher",usageBalanceCash:"Cash",usageBalanceUsed:"Used",usageBalanceLimit:"Limit",oauthWait:"Waiting for authorization…",oauthCancel:"Cancel login",noSessions:"No sessions yet",startWith:"New workspace",inputPlaceholder:"Message pi…",thinking:"Thinking",thinkingOff:"Off",model:"Model",selectModel:"Select model",triggerLoading:"Loading models…",blockedComposer:"This model is unavailable — select one to continue",emptyModels:"No models available.",emptyEfforts:"This model provides no reasoning effort levels.",thinkingUnsupported:"Not supported by this model",thinkingUnsupportedHint:'The model does not declare reasoning support. For custom models, add "reasoning": true (optionally a thinkingLevelMap) to the model in ~/.pi/agent/models.json',toolReadonly:"Read Only",toolStandard:"Workspace Write",toolFull:"Full access",stop:"Stop",send:"Send",imageAttachment:"Image attachment",imageTooLarge:"Each image must be 20 MB or smaller",imageCountLimit:"You can attach up to 20 images",imageTypeUnsupported:"Only JPEG, PNG, WebP, and GIF images are supported",dropToAttach:"Drop to attach",dropToAttachHint:"Images attach to the message; other files (archives, documents) are saved and referenced by path for the agent to read",dropLimits:"Images ≤ 20MB \xb7 up to 20 \xb7 Other files ≤ 100MB \xb7 up to 16",uploading:"Uploading…",uploadFailed:"Upload failed",uploadTooLarge:"Each file must be 100 MB or smaller",uploadCountLimit:"You can attach up to 16 files",attachmentLine:"Attachment: {path} ({size})",cmdMenu:"Commands",slashCatalog:"Commands and skills",skillType:"Skill",cmdCompact:"Compact older conversation history",cmdExport:"Download this session log",cmdModel:"Select the model for this session",cmdNew:"Start a new session",cmdFork:"Fork this session",cmdReload:"Reload extensions, skills and prompt templates (pi /reload)",promptType:"Template",extensionCmdType:"Extension",cmdUnknown:"Unknown command: /{name}. See the / menu in the composer for available commands",extensionDialogTag:"Extension",extensionStatus:"Extension status",contextUsed:"context used",contextUnknown:"Context usage unknown",contextSystem:"System prompt",contextMessages:"Messages",contextTools:"Tools",promptPanel:"Prompt sources",promptRefresh:"Refresh",promptLoading:"Loading…",promptColdHint:"Session not started yet: disk files are listed now; the assembled system prompt and tool definitions appear once the session is running.",promptOriginProject:"project",promptOriginAgent:"user",promptOriginPackage:"package",promptOriginExtension:"extension",promptKindSystem:"System prompt file",promptKindAppend:"Appended prompt",promptKindAgents:"Project memory (AGENTS.md)",promptKindSkill:"Skill prompts",promptKindTemplate:"Prompt templates",promptKindTool:"Tool prompts",promptKindAssembled:"System prompt",promptKindCompacted:"Compaction summary",promptCompactedKey:"Compaction summary in context",promptGuidelines:"Prompt guidelines",promptParameters:"Parameter schema",promptAssembledKey:"Effective system prompt",promptToolBuiltin:"builtin",promptToolExtension:"extension",contextSystemPrompt:"System Prompt",contextSystemTools:"System Tools",contextCustomTools:"Custom Tools",contextMemory:"Memory (AGENTS.md)",contextSkills:"Skills",contextUserMessages:"User Messages",contextAgentText:"Agent Text",contextAgentThinking:"Agent Thinking",contextAgentToolCall:"Agent Tool Call",contextToolOutput:"Tool Output",contextCompacted:"Compacted Data",contextAutoCompactBuffer:"Auto-Compact Buffer",contextFreeSpace:"Free Space",turns:"turns",toolCalls:"tool calls",cost:"cost",duration:"duration",cacheHits:"cache hits",statsCounts:"{turns} turns \xb7 {steps} steps",ttftAverage:"TTFT avg",inputTokens:"Input",outputTokens:"Output",tabChat:"Chat",tabTrajectory:"Trajectory",sessionLog:"Session log",sessionDetails:"Session details",exportJsonl:"Export JSONL",trajTimeline:"Timeline",trajModeSeq:"Sequence",trajModeTime:"Time",trajModeDur:"Duration",trajEmpty:"No trajectory records yet",trajSearchPlaceholder:"Search trajectory",trajNoMatch:"No matching trajectory records",trajInput:"Input",trajModel:"Model",trajTools:"Tools",trajOutput:"Output",trajThink:"Think",trajTime:"Time",trajTurn:"Turn",trajSystem:"System",trajSession:"Session",trajSummary:"Summary",trajPreview:"Preview",trajRaw:"Raw",trajSource:"Source",trajStatus:"Status",trajCompleted:"Completed",trajFailed:"Failed",trajStarted:"Started",trajTokens:"Token usage",trajNoContent:"This record has no displayable content",encodingLossWarning:"This historical tool output was already damaged when saved. Unrecoverable lines are hidden; the current Pi SDK forces new PowerShell output to UTF-8.",ttft:"TTFT",decode:"Decode",inspector:"Record inspector",setGeneral:"General",setModels:"Models",enterBehavior:"Enter while busy",enterBehaviorDesc:"Only while pi is running; Ctrl/Cmd+Enter sends the other way",enterQueue:"Queue: sent after this turn ends",enterSteer:"Steer: delivered after the current tool call",setSkills:"Skills",importSessions:"Import sessions",importDesc:"Losslessly import conversations from Codex / Claude Code / Grok / ZCode / dsh / opencode on this machine into pi sessions: text, thinking, tool calls and results, timestamps and usage are all kept. If the original project directory still exists locally the session lands in that workspace; otherwise it falls back to the workspace selected below. Source data is only read, never modified.",importRescan:"Rescan",importScanning:"Scanning...",importSourceClaude:"Claude Code",importSourceCodex:"Codex",importSourceGrok:"Grok",importSourceZcode:"ZCode",importSourceDsh:"dsh",importSourceOpencode:"opencode",importSourceError:"{source} scan failed: {message}",importGroupCount:"{n} sessions \xb7 {imported} imported",importPickSource:"Choose a source",importLimitHint:"Only the {n} most recent conversations per source are scanned",importLimitHintTooltip:"To see older sessions, raise SCAN_LIMIT_PER_SOURCE in src/lib/session-import/index.ts",importSelectAll:"Select group",importSelectNone:"Clear group",importClearSelection:"Clear",importRun:"Import selected ({n})",importRunning:"Importing...",importFallbackWorkspace:"Fallback workspace",importFallbackHint:"Used when the original project folder is gone",importWhereGoes:"Destination",importGoesOriginal:"Back to its original workspace",importGoesFallback:"Original folder is gone — uses the fallback workspace",importAlready:"Imported",importUntitled:"(untitled)",importNoProject:"(no project directory)",importMessages:"{n} messages",importEmpty:"No importable local sessions found",importReportSummary:"Imported {imported} \xb7 skipped {skipped} \xb7 failed {failed}",drawerPanel:"Drawer",drawerSections:"Drawer sections",drawerPrompts:"Prompts",setPlugins:"Plugins",setRemote:"Remote access",remoteBuiltin:"Built-in plugin",remoteLanTitle:"Local network",remoteLanHint:"Devices on the same Wi-Fi can open the address below; the mobile layout is already applied. On by default. Links carry the login token: copy one to your phone and it signs in directly. The token is a credential — don't share it.",remotePublicTitle:"Public access",remotePublicHint:"Once on, any browser can open it with nothing to install. Cloudflare assigns a random address that changes on every start. The link carries the login token too.",remoteLinkCopied:"Copied (with token)",remoteStart:"Turn on",remoteStop:"Turn off",remoteWorking:"Starting…",remoteRunning:"Running",remoteStopped:"Off",remotePending:"Address created, taking effect…",remoteEngineMissing:"cloudflared not found. Install it and retry, or point PIWEB_CLOUDFLARED at it.",remoteFailed:"Action failed",remoteBlockedAuth:"Remote access is unavailable because authentication is off — it would be an open, password-free entry. Start with the piweb launcher, or set PI_WEB_AUTH=1.",remoteBlockedDev:"Development mode serves this machine only, so remote access is unavailable. Build first, then start in production mode.",remoteSessionsTitle:"Signed-in devices",remoteSessionsHint:"Phones and other computers stay signed in for 30 days. If a device is lost or a link leaked, make every device (including this one) sign in again with the launch token.",remoteSignOutAll:"Sign out all devices",remoteSignOutAllConfirm:"Click again to confirm",appearance:"Appearance",appearanceMode:"Light / Dark",themeLight:"Light",themeDark:"Dark",themeSystem:"System",themeSilverSteel:"Silver & Steel",themeLimestoneCoal:"Limestone & Coal",themeLinenMoss:"Linen & Moss",themeNordPaper:"Nord & Paper",themePebrel:"Pebrel",themeDsh:"Sea & Ink",fontSize:"Font size",fontUiSize:"UI font size",fontUiSizeDesc:"Sidebar, buttons, labels and other UI text",fontChatSize:"Chat font size",fontChatSizeDesc:"Message body, user bubbles and the composer",fontUiFamily:"UI font family",fontUiFamilyDesc:"Font used by the sidebar, buttons, labels and other UI text",fontMonoFamily:"Code font family",fontMonoFamilyDesc:"Monospace font used by code blocks, diffs and inline code",fontCustom:"Custom…",fontCustomPlaceholder:"Font stack, e.g. Fira Code, monospace",language:"Language",openConfigFile:"Open config file",providerAuthOk:"Configured",providerReady:"Request authentication ready",authUnavailable:"Credentials unavailable",credentialSource:"Credential: {source}",authSourceRuntime:"runtime",authSourceEnvironment:"environment",authSourceCommand:"models.json command",authSourceProvider:"provider config",apiKey:"API Key",apiKeyStored:"Saved; leave blank to keep it",providerIdImmutable:"A Provider ID cannot be changed after creation. Delete and recreate it to rename it.",modelConfigReopen:"Model configuration saved and applied. Sessions that are answering pick it up after the current turn.",customModelIdentityNotice:"A custom model ID is only a route name sent to that API endpoint. PiWeb does not automatically download, attach, or identify local Ollama models.",customApiKeyHint:"Leave blank to use auth.json. Keyless local/private services (Ollama etc.) get a placeholder key automatically on save.",modelsTitle:"Models",modelsDesc:"Enter an API key for each provider to use its models.",addProvider:"Add provider",addCustomProvider:"Add custom provider",customProviderTitle:"Custom provider",edit:"Edit",customBadge:"Custom",providerLabel:"Provider",apiType:"API type",modelsList:"Models (one ID per line)",baseUrl:"Base URL",apiAddress:"API address",apiProtocol:"API protocol",apiKeyOptional:"Enter an API key, or leave blank to use environment authentication",customSettings:"Custom settings",providerDefault:"Provider default",selectProvider:"Select provider",searchProviders:"Search provider name or ID",noProviderMatches:"No matching providers",modelCount:"{count} models",providerId:"Provider ID",providerIdHint:"A lowercase identifier that uniquely identifies this provider in requests and derives its credential name.",providerIdInvalid:"Use lowercase letters, numbers, and single hyphen-separated segments only.",providerIdTaken:"This Provider ID already exists.",displayName:"Display name",displayNameOptional:"Display name (optional)",modelCatalog:"Model catalog",discoverModels:"Fetch available models",allowPrivateDiscovery:"Allow local/private",allowPrivateHint:"Check this when the model address points to loopback or a private network (Ollama, LM Studio, one-api gateways) to allow this probe; chat requests are not affected",discoveringModels:"Fetching...",usingDefaultModels:"Using Pi SDK default models \xb7 {count}",customModelsRequired:"Add at least one model ID that can be sent",modelCatalogEmptyBuiltin:"No model overrides. The model selector will continue using Pi SDK's live official catalog.",modelCatalogEmptyCustom:"No models will appear in the selector. Add at least one model ID.",addModel:"Add model",modelId:"Model ID",createProvider:"Create provider",saving:"Saving...",setKey:"Save key",removeKey:"Remove key",removeOAuth:"Remove OAuth",confirmRemoveOAuth:'Remove the OAuth login for "{name}"? You will need to log in again to use it.',confirmRemoveProvider:'Delete provider "{name}" and its configuration?',confirmRemoveKey:'Remove the saved key for "{name}"?',customProviders:"Custom providers (models.json)",toolsSection:"Tools",toolsSectionDesc:"The preset picks the default tools for new sessions; with a session open you can toggle its tools individually (current session only).",toolsCurrentSession:"Current session",toolsActiveCount:"{n}/{total} enabled",toolsNoSession:"Open a session to see and toggle its available tools.",securityToolPreset:"Permission",securityToolPresetDesc:"Switch the current tool set; Workspace Write includes bash and is not a filesystem sandbox",securityTrust:"Project trust",securityTrustDesc:"Auto-trust projects containing .pi/ resources (writes pi settings.json)",trustAsk:"Ask every time",trustAlways:"Always trust",trustNever:"Never trust",versionPiweb:"PiWeb version",versionPiwebDesc:"Version of this web app; click to open the repo",versionPi:"Pi version",versionPiDesc:"Version of the pi agent engine; click to open the repo",checkUpdate:"Check for updates",checkingUpdate:"Checking…",upToDate:"Up to date",updateTo:"Update to {v}",updatingNow:"Updating…",updatedTo:"Updated to {v}; restart PiWeb to apply",updateFailed:"Update failed",updateManualHint:"Stop piweb, then run the command above (Windows cannot replace a running installation)",skillsDesc:"Disabled skills are hidden from the system prompt and only callable via /skill:name",confirmDeleteSkill:'Delete skill "{name}"? Its skill directory will be removed and cannot be recovered.',deleteSkillHint:"Delete the skill directory",skillDeletePackageHint:"package skill: use disable",scopeGlobal:"Global",scopeProject:"Project",scopePackage:"Package",viewSkillFile:"View SKILL.md",packages:"Installed pi packages",packagesEmpty:"No pi packages installed",addPackage:"Install pi package",addPackagePlaceholder:"npm:pkg / git:https://… / local path",installLocal:"Install into current project (-l)",install:"Install",uninstall:"Uninstall",confirmUninstallPackage:'Uninstall "{source}"?',update:"Update",pluginConfig:"Plugin config",pluginList:"Plugin list",pluginPageDesc:"Configure and view installed plugins for this deployment.",searchPlugins:"Search plugins",enabled:"Enabled",disabled:"Disabled",enablePlugin:"Enable",disablePlugin:"Disable",updating:"Updating...",uninstalling:"Uninstalling...",updateSuccess:"Updated successfully",uninstallSuccess:"Uninstalled",extensionsEmpty:"No loaded extensions",extensionLoadError:"Failed to load",resourceDiagnostics:"Resource diagnostics",installing:"Installing…",installSuccess:"Installed and loaded",reloadedSessions:"Reloaded: {loaders} loaders \xb7 {sessions} sessions",projectTrustBanner:"This project has .pi/ extensions or skills; pi loads and runs them only if you trust the project",projectTrustBannerNever:"This project's .pi/ extensions and skills are marked untrusted and will not load",projectTrustAllow:"Trust and load",projectTrustDeny:"Do not trust",projectTrustForget:"Ask again",projectTrustTrusted:"Project trusted",projectTrustUntrusted:"Project not trusted",resources:"carries",toastSaved:"Saved",toastError:"Operation failed",running:"Running",projectPanel:"Project",growthScopeRound:"This round",growthScopeSession:"Session total",growthOnlyChanges:"Changes only",growthPickRound:"Select round",growthRoundJump:"Enter round number...",growthRoundJumpHint:"Type a round number and press Enter to jump",growthPrev:"Previous round",growthNext:"Next round",growthRoundPosition:"Round {current}/{total}",growthRecordNow:'Record now: save the current changes as "Your changes"',growthRecordNone:"No new changes",growthNoRounds:"Nothing recorded yet. Send pi a message and each round's changes will show up here.",growthLoading:"Loading history…",growthNoChangesRound:"No file changes in this round",growthNoSession:"Open or start a session to watch the project grow here.",growthUnavailable:"git was not found on this machine; project growth is unavailable",growthUnavailableFallback:"Growth history is unavailable (no usable git); showing the current directory structure",growthConsentTitle:"Turn on growth history for this workspace?",growthConsentNotGit:"Growth history saves each pi turn's changes as git commits so you can review and compare them. This folder is not a git repository yet; turning it on runs git init here (creates a .git folder).",growthConsentNested:"Growth history saves each pi turn's changes as git commits so you can review and compare them. This folder is inside another repository ({parent}); turning it on creates a nested git repository here, which the outer repository will see as a sub-repository.",growthConsentNote:"Commits live on a private ref (refs/piweb/rounds/…) and never touch your branches or index. The choice is remembered per workspace.",growthConsentAllow:"Turn on and create repository",growthConsentDecline:"Don't record",growthRoundLabel:"Round {n}",growthKindUser:"Your changes",growthRoundFiles:"{n} files",growthJumpToChat:"Show in chat",growthRunning:"Round in progress…",growthStatusAborted:"Aborted",growthStatusError:"Error",growthStatD:"Deleted",growthPending:"Writing…",growthLazyDir:"Current disk entry, not recorded in the selected round",growthTruncated:"Too many changes in this round; showing the first 2000",chatRoundChanged:"This round changed {n} files",chatRoundNoChanges:"No file changes this round",chatRoundShow:"Show this round in the project panel",growthExpandAll:"Expand all",growthCollapseAll:"Collapse all",growthFilter:"Filter…",viewerModeDiff:"Changes",viewerModeContent:"Content",viewerModeRender:"Rendered",viewerFold:"Fold unchanged",viewerUnfold:"Show unchanged",viewerFoldedLines:"\xb7\xb7\xb7 {n} unchanged lines \xb7\xb7\xb7",viewerPrevChange:"Previous change",viewerNextChange:"Next change",viewerFullscreen:"Fullscreen",viewerExitFullscreen:"Exit fullscreen",viewerQuickOpen:"Type a file name to open…",viewerQuickOpenEmpty:"No matching files",viewerNoChanges:"No changes to this file in this scope",viewerDeleted:"This file was deleted in this round; showing its last content",viewerHistorical:"This file is no longer in the current snapshot; showing its last recorded content",viewerMissing:"This file is no longer in the current snapshot or on disk",viewerPatchTruncated:"Diff too large; truncated",viewerCloseTab:"Close tab",viewerNotInSnapshot:"Not in the snapshot (over 1MB or excluded); showing the current content from disk",viewerLoadFailed:"Failed to load",viewerEmpty:"Pick a file from the tree on the left"}},h=(0,e.createContext)({lang:"zh",setLang:()=>{},t:f});function i({children:a}){let[b,c]=(0,e.useState)("zh"),f=(0,e.useCallback)(a=>{c(a),localStorage.setItem("piweb.lang",a)},[]);return(0,d.jsx)(h.Provider,{value:{lang:b,setLang:f,t:g[b]},children:a})}function j(){return(0,e.useContext)(h)}},96487:()=>{}};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"use strict";exports.id=924,exports.ids=[393,924],exports.modules={1175:(a,b,c)=>{c.d(b,{Fu:()=>h}),c(77598),c(73024);var d=c(48161),e=c.n(d),f=c(76760),g=c.n(f);function h(){let a=process.env.PI_CODING_AGENT_DIR;if(a)return"~"===a?e().homedir():a.startsWith("~/")||a.startsWith("~\\")?g().join(e().homedir(),a.slice(2)):a;return g().join(e().homedir(),".pi","agent")}},3924:(a,b,c)=>{c.d(b,{remoteBlocked:()=>p,remoteLanEnabled:()=>s,startLan:()=>u}),c(31421),c(73024),c(44708);var d=c(48161),e=c.n(d);c(76760);var f=c(75393);c(1175);var g=c(37067),h=c.n(g),i=c(57075),j=c(38522),k=c.n(j);c(77030);let l=JSON.parse('{"A":"/*\\n * 手机端适配。不改 PiWeb,只在经代理的远程页面上生效\\n * (本机直连 127.0.0.1:30141 的桌面页面完全不加载它)。\\n *\\n * 取值参照 dsh-remote 为 DSH 定的那套移动适配(同作者),并针对 PiWeb 的实测问题:\\n * 390px 下输入框 304px、markdown 表格 442px 超出视口、底部统计行被截断。\\n */\\n@media (max-width: 840px) {\\n\\t/* 1) 输入框自适应高度失控。\\n\\t 实测:视口 390 → 304px,500 → 43px,700+ → 22px;而自然内容高始终 22px。\\n\\t 原因在 ChatInput 的 autoSize():它把\\"被 flex 拉伸后\\"的 scrollHeight 写进了\\n\\t inline height,写回后又把自己撑住,形成自锁。inline 样式不是 important,\\n\\t 所以这里用 max-height !important 把它夹住。 */\\n\\ttextarea {\\n\\t\\tmax-height: 132px !important;\\n\\t\\toverflow-y: auto !important;\\n\\t}\\n\\n\\t/* 2) Markdown 宽表格超出视口被裁掉(实测 442 > 390,body 又是 overflow-x:hidden,\\n\\t 等于右侧内容既看不到也滑不到)。让表格自己横向滚动。 */\\n\\t.md table {\\n\\t\\tdisplay: block !important;\\n\\t\\tmax-width: 100% !important;\\n\\t\\toverflow-x: auto !important;\\n\\t\\t-webkit-overflow-scrolling: touch;\\n\\t}\\n\\n\\t/* 3) 全局溢出护栏(dsh-remote 同款):任何一块都不许把文档撑宽 */\\n\\thtml,\\n\\tbody {\\n\\t\\tmax-width: 100vw !important;\\n\\t\\toverflow-x: hidden !important;\\n\\t}\\n\\tpre {\\n\\t\\tmax-width: 100% !important;\\n\\t\\toverflow-x: auto !important;\\n\\t\\t-webkit-overflow-scrolling: touch;\\n\\t}\\n\\timg,\\n\\tsvg,\\n\\tvideo,\\n\\tcanvas {\\n\\t\\tmax-width: 100% !important;\\n\\t}\\n\\n\\t/* 4) 底部统计行原本 nowrap + ellipsis,手机上「| 输入 2…」之后永远看不到。\\n\\t 改成可横向滑动,滚动条隐藏,信息不再丢。 */\\n\\tdiv.text-center > div.overflow-hidden.text-ellipsis.whitespace-nowrap {\\n\\t\\toverflow-x: auto !important;\\n\\t\\toverflow-y: hidden !important;\\n\\t\\ttext-overflow: clip !important;\\n\\t\\t-webkit-overflow-scrolling: touch;\\n\\t\\tscrollbar-width: none;\\n\\t}\\n\\tdiv.text-center > div.overflow-hidden.text-ellipsis.whitespace-nowrap::-webkit-scrollbar {\\n\\t\\tdisplay: none;\\n\\t}\\n\\n\\t/* 5) 给手机的手势条留位置(没有 insets 的设备 env() 为 0,等于没写) */\\n\\t.pi-main {\\n\\t\\tpadding-bottom: env(safe-area-inset-bottom) !important;\\n\\t}\\n\\n\\t/* 6) 左上角的抽屉按钮。原来是个悬浮的圆角方块(12px/12px、34px),盖在内容上、\\n\\t 和右边那排图标也不在一条水平线上。按 dsh-remote 对 DSH 左侧的做法收成贴角圆形,\\n\\t 尺寸和位置改成与右侧图标完全一致(实测右侧图标是 top 12 / 30\xd730,中心 y=27),\\n\\t 这样整行对齐,按钮底边 42 也在头部分隔线(y=43)之上,不会压住那条线。 */\\n\\t.pi-mobile-menu {\\n\\t\\twidth: 30px !important;\\n\\t\\theight: 30px !important;\\n\\t\\tborder-radius: 999px !important;\\n\\t\\tleft: calc(env(safe-area-inset-left) + 12px) !important;\\n\\t\\ttop: calc(env(safe-area-inset-top) + 12px) !important;\\n\\t}\\n\\t.pi-main > .hairline-b {\\n\\t\\tpadding-left: 52px !important;\\n\\t}\\n\\n\\t/* 7) 右侧大纲导轨是绝对定位的(right-2 + 约 34px 宽的竖条),正文和用户气泡\\n\\t 会从它下面穿过去。不动条宽——那是层级信息——而是把导轨贴边收窄,\\n\\t 再给滚动区留出它实际占的宽度。 */\\n\\t.outline-rail {\\n\\t\\tright: 2px !important;\\n\\t}\\n\\t.outline-rail > div {\\n\\t\\tpadding-left: 6px !important;\\n\\t\\tpadding-right: 2px !important;\\n\\t}\\n\\t.pi-main div.min-h-0.flex-1.overflow-y-auto {\\n\\t\\tpadding-right: 30px !important;\\n\\t}\\n\\n\\t/* 8) 设置弹窗:高度用 100vh(移动端的大视口),内容列又没有 min-height:0\\n\\t 也没有 overflow-y,于是 1986px 的内容被 overflow:hidden 裁在 828px 里,\\n\\t 手机上完全滑不动。实测 client=828 / scroll=1986。 */\\n\\t.settings-dialog {\\n\\t\\theight: calc(100vh - 16px) !important;\\n\\t}\\n\\t.settings-dialog > div:not(.settings-nav) {\\n\\t\\tmin-height: 0 !important;\\n\\t\\toverflow-y: auto !important;\\n\\t\\t-webkit-overflow-scrolling: touch;\\n\\t}\\n\\n\\t/* 9) 模型 / 思考等级浮层锚在胶囊自己的 relative 容器上,right-0 是**胶囊**右缘,\\n\\t 312px 往左展开就顶出屏幕左边(实测 left 为负)。把胶囊容器解除定位,\\n\\t 浮层改用整张输入卡(上一层 relative)做定位父级,right-0 落在卡片右缘就装得下。\\n\\t :has() 在移动端 Safari 15.4+ / Chrome 105+ 都可用。 */\\n\\tdiv.relative:has(> button.chip[aria-haspopup=\\"menu\\"]) {\\n\\t\\tposition: static !important;\\n\\t}\\n\\n\\t/* 10) 设置→模型 的提供方卡片:那一行是 nowrap,中间的名字列被右侧一串按钮挤成\\n\\t 0 宽(实测 w=0),于是「凭据: auth.json」竖着拆行、「编辑」拆成「编/辑」、\\n\\t 右侧的按钮还被裁掉。手机上让这行能换行,并给名字列一个真实的最小宽度。 */\\n\\t.settings-dialog div.flex.items-center.gap-3:has(> div.min-w-0.flex-1) {\\n\\t\\tflex-wrap: wrap !important;\\n\\t\\trow-gap: 8px !important;\\n\\t}\\n\\t.settings-dialog div.flex.items-center.gap-3:has(> div.min-w-0.flex-1) > div.min-w-0.flex-1 {\\n\\t\\tflex: 1 1 140px !important;\\n\\t\\tmin-width: 140px !important;\\n\\t}\\n\\n\\t/* 11) 设置里 Row 那一套([文字列][控件列] 两栏)。控件列是 flex-none,\\n\\t 有的行右侧很宽(「开关 + 两个数字输入框」≈272px、「繁忙时 Enter」的下拉≈233px),\\n\\t 于是 390px 下文字列只剩 70px 左右,中文按每行一两字竖排,行高被撑到\\n\\t 122px / 218px(实测 70\xd7122、69\xd7218)。\\n\\t 试过的几种写法与实测结论:\\n\\t - 只给文字列 flex 增长权重:完全没用(那行没有空闲空间)\\n\\t - 只缩小 gap:只能缓解(70\xd7122 → 86\xd798)\\n\\t - 让所有 Row 都上下排(flex:1 1 100%):能修好,但把本来正常的行也撑高\\n\\t (界面语言 53→85、字体步进 95→105),是密度回退\\n\\t - 正解:文字列 flex-basis 设 0、只留 min-width 当\\"不许被压到多窄\\"的下限。\\n\\t 换行判断用的是 flex-basis(max-content 会很大,所以上一版全换行了),\\n\\t 设成 0 之后判断就只看 min-width:\\n\\t 控件窄的行(界面语言 77px、字体步进 116px)→ 仍并排,保持紧凑\\n\\t 控件宽的行(272px / 233px)→ 控件换到下一行,文字拿满 326px\\n\\t 实测:界面语言 53 不变、界面字体 95→71、繁忙时Enter 239→135、\\n\\t 自动压缩 143→111、自动重试 119→111,全部不再竖排。 */\\n\\t.settings-dialog div.hairline-b.gap-6 {\\n\\t\\tflex-wrap: wrap !important;\\n\\t\\tgap: 8px !important;\\n\\t}\\n\\t.settings-dialog div.hairline-b.gap-6 > div.min-w-0 {\\n\\t\\tflex: 1 1 0 !important;\\n\\t\\tmin-width: 45% !important;\\n\\t}\\n\\t.settings-dialog div.hairline-b.gap-6 > div.flex-none > div.flex.items-center {\\n\\t\\tflex-wrap: wrap !important;\\n\\t\\tjustify-content: flex-end !important;\\n\\t\\trow-gap: 6px !important;\\n\\t}\\n\\n\\t/* 12) 外观主题卡片。卡片是 flex: 1 1 150px 的两列网格,但左右各留 32px 内边距,\\n\\t 159px 的卡片只剩 95px 给标题,于是「石灰与煤炭」「亚麻与苔绿」掉到第二行,\\n\\t 卡片高度变成 110px 而其余是 88px,网格参差(实测 6 张卡:4 张 88 / 2 张 110)。\\n\\t 把左右内边距收到 10px,6 张卡全部回到 88px,标题一行放得下。 */\\n\\t.settings-dialog button[aria-pressed] {\\n\\t\\tpadding-left: 10px !important;\\n\\t\\tpadding-right: 10px !important;\\n\\t}\\n\\n\\t/* 13) 可点目标偏小(实测:字体步进器 26\xd726、reset 48\xd724、开关 36\xd720)。\\n\\t 只扩**热区**,绝不改可见尺寸:开关的滑块位置在 PiWeb 里是写死的\\n\\t (left: 18px / 2px),把开关拉宽会让滑块错位、变成被拉长的怪药丸\\n\\t —— 我第一版写的 min-width:44px 就是这个后果,用户报了\\"启动按钮好丑\\"。\\n\\t 另外这里只做**纵向**扩张(左右不扩):字体步进器 −/+/ 之间只有 8px,\\n\\t 横向扩到 44px 会让两个按钮的热区重叠约 10px,点 − 反而命中 +。 */\\n\\t.settings-dialog .icon-btn,\\n\\t.settings-dialog button.h-6,\\n\\t.settings-dialog button.h-5,\\n\\t.settings-dialog [role=\\"switch\\"] {\\n\\t\\tposition: relative !important;\\n\\t}\\n\\t.settings-dialog .icon-btn::after,\\n\\t.settings-dialog button.h-6::after,\\n\\t.settings-dialog button.h-5::after,\\n\\t.settings-dialog [role=\\"switch\\"]::after {\\n\\t\\tcontent: \\"\\" !important;\\n\\t\\tposition: absolute !important;\\n\\t\\tleft: 0 !important;\\n\\t\\tright: 0 !important;\\n\\t\\ttop: 50% !important;\\n\\t\\theight: max(100%, 44px) !important;\\n\\t\\ttransform: translateY(-50%) !important;\\n\\t\\tborder-radius: 999px !important;\\n\\t}\\n}\\n\\n/* 手机上的浮层统一兜底:不许比屏幕宽,不许比屏幕高,超出就自己滚。 */\\n@media (max-width: 840px) {\\n\\t.popover {\\n\\t\\tmax-width: calc(100vw - 16px) !important;\\n\\t\\tmax-height: 420px !important;\\n\\t\\toverflow-y: auto !important;\\n\\t\\t-webkit-overflow-scrolling: touch;\\n\\t}\\n}\\n\\n/* 11) 模型名太长时跑马灯。取值与做法照搬 dsh-remote 对 DSH 的:\\n\\t 名字窗口固定 28vw 并允许被压缩,装得下就完全不动;装不下时由注入的\\n\\t mobile-fit.js 打上 data-piweb-marquee,再由这里的两份伪元素首尾相接匀速左移。\\n\\t 一份走完另一份正好接上(travel 已含间隔),所以循环处看不出接缝。 */\\n@media (max-width: 840px) {\\n\\tbutton.chip[aria-haspopup=\\"menu\\"] > span.truncate {\\n\\t\\tmin-width: 0 !important;\\n\\t\\tmax-width: 28vw !important;\\n\\t}\\n\\t[data-piweb-marquee] {\\n\\t\\tposition: relative !important;\\n\\t\\tdisplay: block !important;\\n\\t\\twidth: 28vw !important;\\n\\t\\tflex: none !important;\\n\\t\\ttext-overflow: clip !important;\\n\\t\\twhite-space: nowrap !important;\\n\\t\\toverflow: hidden !important;\\n\\t\\ttext-indent: 0 !important;\\n\\t\\tcontain: layout paint !important;\\n\\t\\tcolor: transparent !important;\\n\\t\\tline-height: 20px !important;\\n\\t}\\n\\t[data-piweb-marquee]::before,\\n\\t[data-piweb-marquee]::after {\\n\\t\\tcontent: attr(data-piweb-text);\\n\\t\\tposition: absolute;\\n\\t\\ttop: 0;\\n\\t\\tleft: 0;\\n\\t\\tcolor: var(--piweb-marquee-color, var(--dsw-label-primary));\\n\\t\\tfont-size: 13px;\\n\\t\\tline-height: 20px;\\n\\t\\twhite-space: nowrap;\\n\\t\\twill-change: transform;\\n\\t\\ttransform: translate3d(0, 0, 0);\\n\\t\\tanimation: piweb-mfit-marquee var(--piweb-marquee-duration, 8s) linear infinite both;\\n\\t}\\n\\t[data-piweb-marquee]::after {\\n\\t\\tleft: var(--piweb-marquee-text, 0px);\\n\\t}\\n\\t@keyframes piweb-mfit-marquee {\\n\\t\\tfrom { transform: translate3d(0, 0, 0); }\\n\\t\\tto { transform: translate3d(calc(-1 * var(--piweb-marquee-text, 0px)), 0, 0); }\\n\\t}\\n}\\n\\n/* dvh 是\\"实际可见高度\\",比 100vh(移动 Chrome 的大视口)可靠;\\n 不支持时上面那两条固定值兜底。 */\\n@supports (height: 100dvh) {\\n\\t@media (max-width: 840px) {\\n\\t\\ttextarea {\\n\\t\\t\\tmax-height: min(132px, 26dvh) !important;\\n\\t\\t}\\n\\t\\t.popover {\\n\\t\\t\\tmax-height: min(60dvh, 420px) !important;\\n\\t\\t}\\n\\t\\t.settings-dialog {\\n\\t\\t\\theight: calc(100dvh - 16px) !important;\\n\\t\\t}\\n\\t}\\n}\\n","js":"/*\\n * 手机端脚本(配合 mobile-fit.css)。\\n *\\n * 做两件事:\\n * 1) 模型名太长时改成「跑马灯」。做法照搬 dsh-remote 对 DSH 的处理——\\n * 名字窗口固定 28vw,装得下就完全不动;装不下时才把两份文本首尾相接匀速左移,\\n * 一份走完另一份正好接上,循环没有空档。CSS 负责动画,这里只负责\\"量\\"和\\"打标记\\"。\\n * 为什么必须用 JS 量:纯 CSS 判断不了\\"是否真的被截断\\",只能用省略号一裁了之,\\n * 名字的尾巴就永远看不到了。\\n * 2) 设置里「文字 + 开关」那种行,手机上点文字也能切开关。\\n * 手机断点下这行是上下排(见 mobile-fit.css 第 11 条),文字占满一行、开关缩在下面,\\n * 而 PiWeb 只让那个 36\xd720 的小开关可点 —— 用户点最显眼的标题文字毫无反应,\\n * 看起来就是\\"这个开关坏了\\"。实测:点文字 0 次请求,点开关才发请求。\\n */\\n(function () {\\n\\t\\"use strict\\";\\n\\n\\tvar ATTR = \\"data-piweb-marquee\\";\\n\\tvar TEXT_ATTR = \\"data-piweb-text\\";\\n\\tvar TEXT_VAR = \\"--piweb-marquee-text\\";\\n\\tvar DURATION_VAR = \\"--piweb-marquee-duration\\";\\n\\tvar COLOR_VAR = \\"--piweb-marquee-color\\";\\n\\tvar /** 两份文本之间留的间隔,也是 travel 里多出来的那一段 */\\n\\t\\tGAP = 40;\\n\\tvar /** 每秒移动多少像素,太长就慢一点 */\\n\\t\\tSPEED = 22;\\n\\tvar MIN_CYCLE = 6;\\n\\tvar ROW_BOUND_ATTR = \\"data-piweb-row-bound\\";\\n\\n\\t/** 模型胶囊里的名字(ModelSelector 里那个 span.truncate) */\\n\\tfunction label() {\\n\\t\\treturn document.querySelector(\'button.chip[aria-haspopup=\\"menu\\"] > span.truncate\');\\n\\t}\\n\\n\\tfunction apply() {\\n\\t\\tvar el = label();\\n\\t\\tif (!el) return;\\n\\t\\tvar text = el.textContent || \\"\\";\\n\\t\\tif (!text) return;\\n\\n\\t\\t// 同一个名字已经标过就别再动它:重设属性会把 CSS 动画从头开始,看起来是\\"一直重启\\"\\n\\t\\tif (el.hasAttribute(ATTR) && el.getAttribute(TEXT_ATTR) === text) return;\\n\\n\\t\\t// 量必须在\\"静止态\\"下做:先摘掉标记,否则量到的是被 28vw 框死之后的宽度\\n\\t\\tif (el.hasAttribute(ATTR)) el.removeAttribute(ATTR);\\n\\t\\tvar natural = el.scrollWidth;\\n\\t\\tvar windowWidth = el.clientWidth;\\n\\t\\tif (!windowWidth || natural <= windowWidth + 1) return; // 装得下,什么都不做\\n\\n\\t\\tel.style.setProperty(COLOR_VAR, getComputedStyle(el).color);\\n\\t\\tel.style.setProperty(TEXT_VAR, natural + GAP + \\"px\\");\\n\\t\\tel.style.setProperty(DURATION_VAR, Math.max(MIN_CYCLE, (natural + GAP) / SPEED).toFixed(1) + \\"s\\");\\n\\t\\tel.setAttribute(TEXT_ATTR, text);\\n\\t\\tel.setAttribute(ATTR, \\"\\");\\n\\t}\\n\\n\\t/**\\n\\t * 设置里「文字 + 开关」的行:把文字列变成开关的\\"大号按钮\\"。\\n\\t *\\n\\t * 只绑文字列(Row 里那个 min-w-0 的直系子元素),不碰控件列:\\n\\t * 控件列里有数字输入框,整行可点会把\\"点输入框\\"也变成切开关。\\n\\t * React 重渲染会换掉节点,所以每次轮询都重查;用属性做幂等标记,重复绑不会叠加。\\n\\t */\\n\\tfunction bindSwitchRows() {\\n\\t\\tvar switches = document.querySelectorAll(\'.settings-dialog [role=\\"switch\\"]\');\\n\\t\\tfor (var i = 0; i < switches.length; i++) {\\n\\t\\t\\tvar sw = switches[i];\\n\\t\\t\\tvar row = sw.closest(\\".hairline-b\\");\\n\\t\\t\\tif (!row || row.getAttribute(ROW_BOUND_ATTR) === \\"1\\") continue;\\n\\t\\t\\t// Row 的文字列:hairline-b 的直系子元素里带 min-w-0 的那个\\n\\t\\t\\tvar label = null;\\n\\t\\t\\tfor (var c = 0; c < row.children.length; c += 1) {\\n\\t\\t\\t\\tif (row.children[c].classList.contains(\\"min-w-0\\")) { label = row.children[c]; break; }\\n\\t\\t\\t}\\n\\t\\t\\tif (!label) continue;\\n\\t\\t\\trow.setAttribute(ROW_BOUND_ATTR, \\"1\\");\\n\\t\\t\\t(function (button, labelEl) {\\n\\t\\t\\t\\tlabelEl.style.cursor = \\"pointer\\";\\n\\t\\t\\t\\tlabelEl.addEventListener(\\"click\\", function (event) {\\n\\t\\t\\t\\t\\t// 文字里可能有链接/按钮,别抢它们\\n\\t\\t\\t\\t\\tif (event.target.closest(\\"a, button, input, select, textarea\\")) return;\\n\\t\\t\\t\\t\\tif (button.disabled) return;\\n\\t\\t\\t\\t\\tevent.preventDefault();\\n\\t\\t\\t\\t\\tbutton.click();\\n\\t\\t\\t\\t});\\n\\t\\t\\t})(sw, label);\\n\\t\\t}\\n\\t}\\n\\n\\t// 模型名会随会话/选择变化,输入卡也会整体重挂载;轮询最省事,且因为有上面的\\n\\t// 提前返回,稳态下每次只花一个 querySelector。\\n\\tfunction start() {\\n\\t\\tapply();\\n\\t\\tbindSwitchRows();\\n\\t\\tsetInterval(function () { apply(); bindSwitchRows(); }, 800);\\n\\t\\twindow.addEventListener(\\"resize\\", apply, { passive: true });\\n\\t\\twindow.addEventListener(\\"orientationchange\\", apply, { passive: true });\\n\\t}\\n\\n\\tif (document.readyState === \\"loading\\") document.addEventListener(\\"DOMContentLoaded\\", start, { once: true });\\n\\telse start();\\n})();"}'),m="piweb-mobile-fit",n=l.A,o=l.js;function p(a=process.env){return(0,f.authEnabled)(a)?"development"===a.NODE_ENV?"dev":null:"auth"}function q(){let a=globalThis,b=Symbol.for("piweb:remote-supervisor"),c=a[b];if(c)return c;let d={lan:null,tunnel:null,lanError:null,publicError:null,enginePath:null,engineChecked:!1};return a[b]=d,d}function r(a=process.env){for(let b of[a.PIWEB_PORT,a.PORT]){let a=Number(b);if(Number.isInteger(a)&&a>=1&&a<=65535)return a}return 30141}function s(a=process.env){let b;return"0"!==(b=(a.PIWEB_REMOTE_LAN??"").trim().toLowerCase())&&"false"!==b&&"off"!==b&&"no"!==b}function t(){let a=q(),b=a.lan?.port??null;return{plugin:"builtin-remote",targetPort:r(),blocked:p(),lan:{running:!!a.lan,port:b,urls:b?(function(){let a=[];for(let b of Object.values(e().networkInterfaces()))for(let c of b??[])"IPv4"!==c.family||c.internal||c.address.startsWith("169.254.")||a.push(c.address);return a})().map(a=>`http://${a}:${b}`):[],error:a.lanError},public:{running:!!a.tunnel,url:a.tunnel?.url??null,ready:!!a.tunnel?.ready,engine:a.tunnel?"cloudflared":null,engineAvailable:!a.engineChecked||null!==a.enginePath,error:a.publicError}}}function u(a=function(a=process.env){let b=Number(a.PIWEB_REMOTE_LAN_PORT);return Number.isInteger(b)&&b>=1&&b<=65535?b:30142}(),b="0.0.0.0",c=r()){let d=q();if(d.lan)return Promise.resolve(t().lan);if(d.lanStarting)return d.lanStarting;let e=v(a,b,c).finally(()=>{d.lanStarting===e&&(d.lanStarting=null)});return d.lanStarting=e,e}async function v(a,b,c){let d=q();d.lanError=null;let e=function({targetPort:a,targetHost:b="127.0.0.1",css:c=null,js:d=null,log:e=()=>{}}){return h().createServer((f,g)=>{let j,l={...f.headers},n=!!(c||d)&&!("localhost"===(j=(function(a){let b=String(a??"").trim().toLowerCase();if(b.startsWith("[")){let a=b.indexOf("]");return a>=0?b.slice(1,a):b.slice(1)}return 1===(b.match(/:/g)??[]).length?b.slice(0,b.indexOf(":")):b})(l.host).trim().toLowerCase().replace(/^\[|\]$/g,""))||j.endsWith(".localhost")||"::1"===j||"0:0:0:0:0:0:0:1"===j||/^127(?:\.\d{1,3}){3}$/.test(j));n&&String(l.accept??"").includes("text/html")&&(l["accept-encoding"]="identity");let o=h().request({host:b,port:a,method:f.method,path:f.url??"/",headers:l},a=>{let b=String(a.headers["content-type"]??"");if(!n||!b.includes("text/html")){g.writeHead(a.statusCode??502,a.headers),(0,i.pipeline)(a,g,()=>void 0);return}let f=[];a.on("error",a=>{e(`[远程连接] 上游中途断开:${a.message}`),g.destroy()}),a.on("data",a=>f.push(a)),a.on("end",()=>{let b,h=Buffer.concat(f);try{b=Buffer.from(function(a,{css:b=null,js:c=null}={}){if(!b&&!c||a.includes(`id="${m}"`))return a;let d=[];b&&d.push(`<style id="${m}">
|
|
1
|
+
"use strict";exports.id=924,exports.ids=[393,924],exports.modules={1175:(a,b,c)=>{c.d(b,{Fu:()=>h}),c(77598),c(73024);var d=c(48161),e=c.n(d),f=c(76760),g=c.n(f);function h(){let a=process.env.PI_CODING_AGENT_DIR;if(a)return"~"===a?e().homedir():a.startsWith("~/")||a.startsWith("~\\")?g().join(e().homedir(),a.slice(2)):a;return g().join(e().homedir(),".pi","agent")}},3924:(a,b,c)=>{c.d(b,{remoteBlocked:()=>p,remoteLanEnabled:()=>s,startLan:()=>v}),c(31421),c(73024),c(44708);var d=c(48161),e=c.n(d);c(76760);var f=c(75393);c(1175);var g=c(37067),h=c.n(g),i=c(57075),j=c(38522),k=c.n(j);c(77030);let l=JSON.parse('{"A":"/*\\n * 手机端适配。不改 PiWeb,只在经代理的远程页面上生效\\n * (本机直连 127.0.0.1:30141 的桌面页面完全不加载它)。\\n *\\n * 取值参照 dsh-remote 为 DSH 定的那套移动适配(同作者),并针对 PiWeb 的实测问题:\\n * 390px 下输入框 304px、markdown 表格 442px 超出视口、底部统计行被截断。\\n */\\n@media (max-width: 840px) {\\n\\t/* 1) 输入框自适应高度失控。\\n\\t 实测:视口 390 → 304px,500 → 43px,700+ → 22px;而自然内容高始终 22px。\\n\\t 原因在 ChatInput 的 autoSize():它把\\"被 flex 拉伸后\\"的 scrollHeight 写进了\\n\\t inline height,写回后又把自己撑住,形成自锁。inline 样式不是 important,\\n\\t 所以这里用 max-height !important 把它夹住。 */\\n\\ttextarea {\\n\\t\\tmax-height: 132px !important;\\n\\t\\toverflow-y: auto !important;\\n\\t}\\n\\n\\t/* 2) Markdown 宽表格超出视口被裁掉(实测 442 > 390,body 又是 overflow-x:hidden,\\n\\t 等于右侧内容既看不到也滑不到)。让表格自己横向滚动。 */\\n\\t.md table {\\n\\t\\tdisplay: block !important;\\n\\t\\tmax-width: 100% !important;\\n\\t\\toverflow-x: auto !important;\\n\\t\\t-webkit-overflow-scrolling: touch;\\n\\t}\\n\\n\\t/* 3) 全局溢出护栏(dsh-remote 同款):任何一块都不许把文档撑宽 */\\n\\thtml,\\n\\tbody {\\n\\t\\tmax-width: 100vw !important;\\n\\t\\toverflow-x: hidden !important;\\n\\t}\\n\\tpre {\\n\\t\\tmax-width: 100% !important;\\n\\t\\toverflow-x: auto !important;\\n\\t\\t-webkit-overflow-scrolling: touch;\\n\\t}\\n\\timg,\\n\\tsvg,\\n\\tvideo,\\n\\tcanvas {\\n\\t\\tmax-width: 100% !important;\\n\\t}\\n\\n\\t/* 4) 底部统计行原本 nowrap + ellipsis,手机上「| 输入 2…」之后永远看不到。\\n\\t 改成可横向滑动,滚动条隐藏,信息不再丢。 */\\n\\tdiv.text-center > div.overflow-hidden.text-ellipsis.whitespace-nowrap {\\n\\t\\toverflow-x: auto !important;\\n\\t\\toverflow-y: hidden !important;\\n\\t\\ttext-overflow: clip !important;\\n\\t\\t-webkit-overflow-scrolling: touch;\\n\\t\\tscrollbar-width: none;\\n\\t}\\n\\tdiv.text-center > div.overflow-hidden.text-ellipsis.whitespace-nowrap::-webkit-scrollbar {\\n\\t\\tdisplay: none;\\n\\t}\\n\\n\\t/* 5) 给手机的手势条留位置(没有 insets 的设备 env() 为 0,等于没写) */\\n\\t.pi-main {\\n\\t\\tpadding-bottom: env(safe-area-inset-bottom) !important;\\n\\t}\\n\\n\\t/* 6) 左上角的抽屉按钮。原来是个悬浮的圆角方块(12px/12px、34px),盖在内容上、\\n\\t 和右边那排图标也不在一条水平线上。按 dsh-remote 对 DSH 左侧的做法收成贴角圆形,\\n\\t 尺寸和位置改成与右侧图标完全一致(实测右侧图标是 top 12 / 30\xd730,中心 y=27),\\n\\t 这样整行对齐,按钮底边 42 也在头部分隔线(y=43)之上,不会压住那条线。 */\\n\\t.pi-mobile-menu {\\n\\t\\twidth: 30px !important;\\n\\t\\theight: 30px !important;\\n\\t\\tborder-radius: 999px !important;\\n\\t\\tleft: calc(env(safe-area-inset-left) + 12px) !important;\\n\\t\\ttop: calc(env(safe-area-inset-top) + 12px) !important;\\n\\t}\\n\\t.pi-main > .hairline-b {\\n\\t\\tpadding-left: 52px !important;\\n\\t}\\n\\n\\t/* 7) 右侧大纲导轨是绝对定位的(right-2 + 约 34px 宽的竖条),正文和用户气泡\\n\\t 会从它下面穿过去。不动条宽——那是层级信息——而是把导轨贴边收窄,\\n\\t 再给滚动区留出它实际占的宽度。 */\\n\\t.outline-rail {\\n\\t\\tright: 2px !important;\\n\\t}\\n\\t.outline-rail > div {\\n\\t\\tpadding-left: 6px !important;\\n\\t\\tpadding-right: 2px !important;\\n\\t}\\n\\t.pi-main div.min-h-0.flex-1.overflow-y-auto {\\n\\t\\tpadding-right: 30px !important;\\n\\t}\\n\\n\\t/* 8) 设置弹窗:高度用 100vh(移动端的大视口),内容列又没有 min-height:0\\n\\t 也没有 overflow-y,于是 1986px 的内容被 overflow:hidden 裁在 828px 里,\\n\\t 手机上完全滑不动。实测 client=828 / scroll=1986。 */\\n\\t.settings-dialog {\\n\\t\\theight: calc(100vh - 16px) !important;\\n\\t}\\n\\t.settings-dialog > div:not(.settings-nav) {\\n\\t\\tmin-height: 0 !important;\\n\\t\\toverflow-y: auto !important;\\n\\t\\t-webkit-overflow-scrolling: touch;\\n\\t}\\n\\n\\t/* 9) 模型 / 思考等级浮层锚在胶囊自己的 relative 容器上,right-0 是**胶囊**右缘,\\n\\t 312px 往左展开就顶出屏幕左边(实测 left 为负)。把胶囊容器解除定位,\\n\\t 浮层改用整张输入卡(上一层 relative)做定位父级,right-0 落在卡片右缘就装得下。\\n\\t :has() 在移动端 Safari 15.4+ / Chrome 105+ 都可用。 */\\n\\tdiv.relative:has(> button.chip[aria-haspopup=\\"menu\\"]) {\\n\\t\\tposition: static !important;\\n\\t}\\n\\n\\t/* 10) 设置→模型 的提供方卡片:那一行是 nowrap,中间的名字列被右侧一串按钮挤成\\n\\t 0 宽(实测 w=0),于是「凭据: auth.json」竖着拆行、「编辑」拆成「编/辑」、\\n\\t 右侧的按钮还被裁掉。手机上让这行能换行,并给名字列一个真实的最小宽度。 */\\n\\t.settings-dialog div.flex.items-center.gap-3:has(> div.min-w-0.flex-1) {\\n\\t\\tflex-wrap: wrap !important;\\n\\t\\trow-gap: 8px !important;\\n\\t}\\n\\t.settings-dialog div.flex.items-center.gap-3:has(> div.min-w-0.flex-1) > div.min-w-0.flex-1 {\\n\\t\\tflex: 1 1 140px !important;\\n\\t\\tmin-width: 140px !important;\\n\\t}\\n\\n\\t/* 11) 设置里 Row 那一套([文字列][控件列] 两栏)。控件列是 flex-none,\\n\\t 有的行右侧很宽(「开关 + 两个数字输入框」≈272px、「繁忙时 Enter」的下拉≈233px),\\n\\t 于是 390px 下文字列只剩 70px 左右,中文按每行一两字竖排,行高被撑到\\n\\t 122px / 218px(实测 70\xd7122、69\xd7218)。\\n\\t 试过的几种写法与实测结论:\\n\\t - 只给文字列 flex 增长权重:完全没用(那行没有空闲空间)\\n\\t - 只缩小 gap:只能缓解(70\xd7122 → 86\xd798)\\n\\t - 让所有 Row 都上下排(flex:1 1 100%):能修好,但把本来正常的行也撑高\\n\\t (界面语言 53→85、字体步进 95→105),是密度回退\\n\\t - 正解:文字列 flex-basis 设 0、只留 min-width 当\\"不许被压到多窄\\"的下限。\\n\\t 换行判断用的是 flex-basis(max-content 会很大,所以上一版全换行了),\\n\\t 设成 0 之后判断就只看 min-width:\\n\\t 控件窄的行(界面语言 77px、字体步进 116px)→ 仍并排,保持紧凑\\n\\t 控件宽的行(272px / 233px)→ 控件换到下一行,文字拿满 326px\\n\\t 实测:界面语言 53 不变、界面字体 95→71、繁忙时Enter 239→135、\\n\\t 自动压缩 143→111、自动重试 119→111,全部不再竖排。 */\\n\\t.settings-dialog div.hairline-b.gap-6 {\\n\\t\\tflex-wrap: wrap !important;\\n\\t\\tgap: 8px !important;\\n\\t}\\n\\t.settings-dialog div.hairline-b.gap-6 > div.min-w-0 {\\n\\t\\tflex: 1 1 0 !important;\\n\\t\\tmin-width: 45% !important;\\n\\t}\\n\\t.settings-dialog div.hairline-b.gap-6 > div.flex-none > div.flex.items-center {\\n\\t\\tflex-wrap: wrap !important;\\n\\t\\tjustify-content: flex-end !important;\\n\\t\\trow-gap: 6px !important;\\n\\t}\\n\\n\\t/* 12) 外观主题卡片。卡片是 flex: 1 1 150px 的两列网格,但左右各留 32px 内边距,\\n\\t 159px 的卡片只剩 95px 给标题,于是「石灰与煤炭」「亚麻与苔绿」掉到第二行,\\n\\t 卡片高度变成 110px 而其余是 88px,网格参差(实测 6 张卡:4 张 88 / 2 张 110)。\\n\\t 把左右内边距收到 10px,6 张卡全部回到 88px,标题一行放得下。 */\\n\\t.settings-dialog button[aria-pressed] {\\n\\t\\tpadding-left: 10px !important;\\n\\t\\tpadding-right: 10px !important;\\n\\t}\\n\\n\\t/* 13) 可点目标偏小(实测:字体步进器 26\xd726、reset 48\xd724、开关 36\xd720)。\\n\\t 只扩**热区**,绝不改可见尺寸:开关的滑块位置在 PiWeb 里是写死的\\n\\t (left: 18px / 2px),把开关拉宽会让滑块错位、变成被拉长的怪药丸\\n\\t —— 我第一版写的 min-width:44px 就是这个后果,用户报了\\"启动按钮好丑\\"。\\n\\t 另外这里只做**纵向**扩张(左右不扩):字体步进器 −/+/ 之间只有 8px,\\n\\t 横向扩到 44px 会让两个按钮的热区重叠约 10px,点 − 反而命中 +。 */\\n\\t.settings-dialog .icon-btn,\\n\\t.settings-dialog button.h-6,\\n\\t.settings-dialog button.h-5,\\n\\t.settings-dialog [role=\\"switch\\"] {\\n\\t\\tposition: relative !important;\\n\\t}\\n\\t.settings-dialog .icon-btn::after,\\n\\t.settings-dialog button.h-6::after,\\n\\t.settings-dialog button.h-5::after,\\n\\t.settings-dialog [role=\\"switch\\"]::after {\\n\\t\\tcontent: \\"\\" !important;\\n\\t\\tposition: absolute !important;\\n\\t\\tleft: 0 !important;\\n\\t\\tright: 0 !important;\\n\\t\\ttop: 50% !important;\\n\\t\\theight: max(100%, 44px) !important;\\n\\t\\ttransform: translateY(-50%) !important;\\n\\t\\tborder-radius: 999px !important;\\n\\t}\\n}\\n\\n/* 手机上的浮层统一兜底:不许比屏幕宽,不许比屏幕高,超出就自己滚。 */\\n@media (max-width: 840px) {\\n\\t.popover {\\n\\t\\tmax-width: calc(100vw - 16px) !important;\\n\\t\\tmax-height: 420px !important;\\n\\t\\toverflow-y: auto !important;\\n\\t\\t-webkit-overflow-scrolling: touch;\\n\\t}\\n}\\n\\n/* 11) 模型名太长时跑马灯。取值与做法照搬 dsh-remote 对 DSH 的:\\n\\t 名字窗口固定 28vw 并允许被压缩,装得下就完全不动;装不下时由注入的\\n\\t mobile-fit.js 打上 data-piweb-marquee,再由这里的两份伪元素首尾相接匀速左移。\\n\\t 一份走完另一份正好接上(travel 已含间隔),所以循环处看不出接缝。 */\\n@media (max-width: 840px) {\\n\\tbutton.chip[aria-haspopup=\\"menu\\"] > span.truncate {\\n\\t\\tmin-width: 0 !important;\\n\\t\\tmax-width: 28vw !important;\\n\\t}\\n\\t[data-piweb-marquee] {\\n\\t\\tposition: relative !important;\\n\\t\\tdisplay: block !important;\\n\\t\\twidth: 28vw !important;\\n\\t\\tflex: none !important;\\n\\t\\ttext-overflow: clip !important;\\n\\t\\twhite-space: nowrap !important;\\n\\t\\toverflow: hidden !important;\\n\\t\\ttext-indent: 0 !important;\\n\\t\\tcontain: layout paint !important;\\n\\t\\tcolor: transparent !important;\\n\\t\\tline-height: 20px !important;\\n\\t}\\n\\t[data-piweb-marquee]::before,\\n\\t[data-piweb-marquee]::after {\\n\\t\\tcontent: attr(data-piweb-text);\\n\\t\\tposition: absolute;\\n\\t\\ttop: 0;\\n\\t\\tleft: 0;\\n\\t\\tcolor: var(--piweb-marquee-color, var(--dsw-label-primary));\\n\\t\\tfont-size: 13px;\\n\\t\\tline-height: 20px;\\n\\t\\twhite-space: nowrap;\\n\\t\\twill-change: transform;\\n\\t\\ttransform: translate3d(0, 0, 0);\\n\\t\\tanimation: piweb-mfit-marquee var(--piweb-marquee-duration, 8s) linear infinite both;\\n\\t}\\n\\t[data-piweb-marquee]::after {\\n\\t\\tleft: var(--piweb-marquee-text, 0px);\\n\\t}\\n\\t@keyframes piweb-mfit-marquee {\\n\\t\\tfrom { transform: translate3d(0, 0, 0); }\\n\\t\\tto { transform: translate3d(calc(-1 * var(--piweb-marquee-text, 0px)), 0, 0); }\\n\\t}\\n}\\n\\n/* dvh 是\\"实际可见高度\\",比 100vh(移动 Chrome 的大视口)可靠;\\n 不支持时上面那两条固定值兜底。 */\\n@supports (height: 100dvh) {\\n\\t@media (max-width: 840px) {\\n\\t\\ttextarea {\\n\\t\\t\\tmax-height: min(132px, 26dvh) !important;\\n\\t\\t}\\n\\t\\t.popover {\\n\\t\\t\\tmax-height: min(60dvh, 420px) !important;\\n\\t\\t}\\n\\t\\t.settings-dialog {\\n\\t\\t\\theight: calc(100dvh - 16px) !important;\\n\\t\\t}\\n\\t}\\n}\\n","js":"/*\\n * 手机端脚本(配合 mobile-fit.css)。\\n *\\n * 做两件事:\\n * 1) 模型名太长时改成「跑马灯」。做法照搬 dsh-remote 对 DSH 的处理——\\n * 名字窗口固定 28vw,装得下就完全不动;装不下时才把两份文本首尾相接匀速左移,\\n * 一份走完另一份正好接上,循环没有空档。CSS 负责动画,这里只负责\\"量\\"和\\"打标记\\"。\\n * 为什么必须用 JS 量:纯 CSS 判断不了\\"是否真的被截断\\",只能用省略号一裁了之,\\n * 名字的尾巴就永远看不到了。\\n * 2) 设置里「文字 + 开关」那种行,手机上点文字也能切开关。\\n * 手机断点下这行是上下排(见 mobile-fit.css 第 11 条),文字占满一行、开关缩在下面,\\n * 而 PiWeb 只让那个 36\xd720 的小开关可点 —— 用户点最显眼的标题文字毫无反应,\\n * 看起来就是\\"这个开关坏了\\"。实测:点文字 0 次请求,点开关才发请求。\\n */\\n(function () {\\n\\t\\"use strict\\";\\n\\n\\tvar ATTR = \\"data-piweb-marquee\\";\\n\\tvar TEXT_ATTR = \\"data-piweb-text\\";\\n\\tvar TEXT_VAR = \\"--piweb-marquee-text\\";\\n\\tvar DURATION_VAR = \\"--piweb-marquee-duration\\";\\n\\tvar COLOR_VAR = \\"--piweb-marquee-color\\";\\n\\tvar /** 两份文本之间留的间隔,也是 travel 里多出来的那一段 */\\n\\t\\tGAP = 40;\\n\\tvar /** 每秒移动多少像素,太长就慢一点 */\\n\\t\\tSPEED = 22;\\n\\tvar MIN_CYCLE = 6;\\n\\tvar ROW_BOUND_ATTR = \\"data-piweb-row-bound\\";\\n\\n\\t/** 模型胶囊里的名字(ModelSelector 里那个 span.truncate) */\\n\\tfunction label() {\\n\\t\\treturn document.querySelector(\'button.chip[aria-haspopup=\\"menu\\"] > span.truncate\');\\n\\t}\\n\\n\\tfunction apply() {\\n\\t\\tvar el = label();\\n\\t\\tif (!el) return;\\n\\t\\tvar text = el.textContent || \\"\\";\\n\\t\\tif (!text) return;\\n\\n\\t\\t// 同一个名字已经标过就别再动它:重设属性会把 CSS 动画从头开始,看起来是\\"一直重启\\"\\n\\t\\tif (el.hasAttribute(ATTR) && el.getAttribute(TEXT_ATTR) === text) return;\\n\\n\\t\\t// 量必须在\\"静止态\\"下做:先摘掉标记,否则量到的是被 28vw 框死之后的宽度\\n\\t\\tif (el.hasAttribute(ATTR)) el.removeAttribute(ATTR);\\n\\t\\tvar natural = el.scrollWidth;\\n\\t\\tvar windowWidth = el.clientWidth;\\n\\t\\tif (!windowWidth || natural <= windowWidth + 1) return; // 装得下,什么都不做\\n\\n\\t\\tel.style.setProperty(COLOR_VAR, getComputedStyle(el).color);\\n\\t\\tel.style.setProperty(TEXT_VAR, natural + GAP + \\"px\\");\\n\\t\\tel.style.setProperty(DURATION_VAR, Math.max(MIN_CYCLE, (natural + GAP) / SPEED).toFixed(1) + \\"s\\");\\n\\t\\tel.setAttribute(TEXT_ATTR, text);\\n\\t\\tel.setAttribute(ATTR, \\"\\");\\n\\t}\\n\\n\\t/**\\n\\t * 设置里「文字 + 开关」的行:把文字列变成开关的\\"大号按钮\\"。\\n\\t *\\n\\t * 只绑文字列(Row 里那个 min-w-0 的直系子元素),不碰控件列:\\n\\t * 控件列里有数字输入框,整行可点会把\\"点输入框\\"也变成切开关。\\n\\t * React 重渲染会换掉节点,所以每次轮询都重查;用属性做幂等标记,重复绑不会叠加。\\n\\t */\\n\\tfunction bindSwitchRows() {\\n\\t\\tvar switches = document.querySelectorAll(\'.settings-dialog [role=\\"switch\\"]\');\\n\\t\\tfor (var i = 0; i < switches.length; i++) {\\n\\t\\t\\tvar sw = switches[i];\\n\\t\\t\\tvar row = sw.closest(\\".hairline-b\\");\\n\\t\\t\\tif (!row || row.getAttribute(ROW_BOUND_ATTR) === \\"1\\") continue;\\n\\t\\t\\t// Row 的文字列:hairline-b 的直系子元素里带 min-w-0 的那个\\n\\t\\t\\tvar label = null;\\n\\t\\t\\tfor (var c = 0; c < row.children.length; c += 1) {\\n\\t\\t\\t\\tif (row.children[c].classList.contains(\\"min-w-0\\")) { label = row.children[c]; break; }\\n\\t\\t\\t}\\n\\t\\t\\tif (!label) continue;\\n\\t\\t\\trow.setAttribute(ROW_BOUND_ATTR, \\"1\\");\\n\\t\\t\\t(function (button, labelEl) {\\n\\t\\t\\t\\tlabelEl.style.cursor = \\"pointer\\";\\n\\t\\t\\t\\tlabelEl.addEventListener(\\"click\\", function (event) {\\n\\t\\t\\t\\t\\t// 文字里可能有链接/按钮,别抢它们\\n\\t\\t\\t\\t\\tif (event.target.closest(\\"a, button, input, select, textarea\\")) return;\\n\\t\\t\\t\\t\\tif (button.disabled) return;\\n\\t\\t\\t\\t\\tevent.preventDefault();\\n\\t\\t\\t\\t\\tbutton.click();\\n\\t\\t\\t\\t});\\n\\t\\t\\t})(sw, label);\\n\\t\\t}\\n\\t}\\n\\n\\t// 模型名会随会话/选择变化,输入卡也会整体重挂载;轮询最省事,且因为有上面的\\n\\t// 提前返回,稳态下每次只花一个 querySelector。\\n\\tfunction start() {\\n\\t\\tapply();\\n\\t\\tbindSwitchRows();\\n\\t\\tsetInterval(function () { apply(); bindSwitchRows(); }, 800);\\n\\t\\twindow.addEventListener(\\"resize\\", apply, { passive: true });\\n\\t\\twindow.addEventListener(\\"orientationchange\\", apply, { passive: true });\\n\\t}\\n\\n\\tif (document.readyState === \\"loading\\") document.addEventListener(\\"DOMContentLoaded\\", start, { once: true });\\n\\telse start();\\n})();"}'),m="piweb-mobile-fit",n=l.A,o=l.js;function p(a=process.env){return(0,f.authEnabled)(a)?"development"===a.NODE_ENV?"dev":null:"auth"}function q(){let a=globalThis,b=Symbol.for("piweb:remote-supervisor"),c=a[b];if(c)return c;let d={lan:null,tunnel:null,lanError:null,publicError:null,enginePath:null,engineChecked:!1};return a[b]=d,d}function r(a=process.env){for(let b of[a.PIWEB_PORT,a.PORT]){let a=Number(b);if(Number.isInteger(a)&&a>=1&&a<=65535)return a}return 30141}function s(a=process.env){let b;return"0"!==(b=(a.PIWEB_REMOTE_LAN??"").trim().toLowerCase())&&"false"!==b&&"off"!==b&&"no"!==b}let t=/vmware|virtualbox|vboxnet|vethernet|hyper-v|wsl|docker|^br-|^veth/i;function u(){let a=q(),b=a.lan?.port??null;return{plugin:"builtin-remote",targetPort:r(),blocked:p(),lan:{running:!!a.lan,port:b,urls:b?(function(a=e().networkInterfaces()){let b=[],c=[];for(let[d,e]of Object.entries(a))for(let a of e??[])!("IPv4"!==a.family||a.internal||a.address.startsWith("169.254."))&&(/^198\.1[89]\./.test(a.address)||(t.test(d)?c:b).push(a.address));return[...b,...c]})().map(a=>`http://${a}:${b}`):[],error:a.lanError},public:{running:!!a.tunnel,url:a.tunnel?.url??null,ready:!!a.tunnel?.ready,engine:a.tunnel?"cloudflared":null,engineAvailable:!a.engineChecked||null!==a.enginePath,error:a.publicError}}}function v(a=function(a=process.env){let b=Number(a.PIWEB_REMOTE_LAN_PORT);return Number.isInteger(b)&&b>=1&&b<=65535?b:30142}(),b="0.0.0.0",c=r()){let d=q();if(d.lan)return Promise.resolve(u().lan);if(d.lanStarting)return d.lanStarting;let e=w(a,b,c).finally(()=>{d.lanStarting===e&&(d.lanStarting=null)});return d.lanStarting=e,e}async function w(a,b,c){let d=q();d.lanError=null;let e=function({targetPort:a,targetHost:b="127.0.0.1",css:c=null,js:d=null,log:e=()=>{}}){let f=new(h()).Agent({keepAlive:!0,scheduling:"lifo",timeout:5e3}),g=h().createServer((g,j)=>{let l,n={...g.headers},o=!!(c||d)&&!("localhost"===(l=(function(a){let b=String(a??"").trim().toLowerCase();if(b.startsWith("[")){let a=b.indexOf("]");return a>=0?b.slice(1,a):b.slice(1)}return 1===(b.match(/:/g)??[]).length?b.slice(0,b.indexOf(":")):b})(n.host).trim().toLowerCase().replace(/^\[|\]$/g,""))||l.endsWith(".localhost")||"::1"===l||"0:0:0:0:0:0:0:1"===l||/^127(?:\.\d{1,3}){3}$/.test(l));o&&String(n.accept??"").includes("text/html")&&(n["accept-encoding"]="identity");let p=h().request({host:b,port:a,method:g.method,path:g.url??"/",headers:n,agent:f},a=>{let b=String(a.headers["content-type"]??"");if(!o||!b.includes("text/html")){j.writeHead(a.statusCode??502,a.headers),(0,i.pipeline)(a,j,()=>void 0);return}let f=[];a.on("error",a=>{e(`[远程连接] 上游中途断开:${a.message}`),j.destroy()}),a.on("data",a=>f.push(a)),a.on("end",()=>{let b,g=Buffer.concat(f);try{b=Buffer.from(function(a,{css:b=null,js:c=null}={}){if(!b&&!c||a.includes(`id="${m}"`))return a;let d=[];b&&d.push(`<style id="${m}">
|
|
2
2
|
${b}
|
|
3
3
|
</style>`),c&&d.push(`<script id="${m}-js">
|
|
4
4
|
${c}
|
|
5
5
|
</script>`);let e=d.join("\n"),f=a.indexOf("</head>");if(f>=0)return`${a.slice(0,f)}${e}
|
|
6
|
-
${a.slice(f)}`;let g=a.indexOf("<body");if(g>=0){let b=a.indexOf(">",g);if(b>=0)return`${a.slice(0,b+1)}${e}${a.slice(b+1)}`}return e+a}((function(a,b){let c=String(b??"").toLowerCase();if(!c||"identity"===c)return a;if("gzip"===c||"x-gzip"===c)return k().gunzipSync(a);if("deflate"===c)return k().inflateSync(a);if("br"===c)return k().brotliDecompressSync(a);throw Error(`不支持的 content-encoding:${b}`)})(
|
|
6
|
+
${a.slice(f)}`;let g=a.indexOf("<body");if(g>=0){let b=a.indexOf(">",g);if(b>=0)return`${a.slice(0,b+1)}${e}${a.slice(b+1)}`}return e+a}((function(a,b){let c=String(b??"").toLowerCase();if(!c||"identity"===c)return a;if("gzip"===c||"x-gzip"===c)return k().gunzipSync(a);if("deflate"===c)return k().inflateSync(a);if("br"===c)return k().brotliDecompressSync(a);throw Error(`不支持的 content-encoding:${b}`)})(g,a.headers["content-encoding"]).toString("utf8"),{css:c,js:d}),"utf8")}catch(c){e(`[远程连接] 注入失败,原样返回:${c instanceof Error?c.message:String(c)}`);let b={...a.headers};delete b["content-encoding"],delete b["content-length"],j.writeHead(a.statusCode??200,b),j.end(g);return}let h={...a.headers};delete h["content-encoding"],delete h["transfer-encoding"],delete h.etag,h["content-length"]=String(b.byteLength),h["cache-control"]="no-store",j.writeHead(a.statusCode??200,h),j.end(b)})}),q=!1;p.on("error",a=>{q||(e(`[远程连接] 代理连不上 PiWeb:${a.message}`),j.headersSent||j.writeHead(502,{"content-type":"text/plain; charset=utf-8"}),j.end(`[远程连接] 连不上 PiWeb(${a.message})`))}),j.on("close",()=>{j.writableFinished||(q=!0,p.destroy())}),g.pipe(p)});return g.on("close",()=>f.destroy()),g}({targetPort:c,css:n,js:o,log:a=>console.warn(a)});try{await new Promise((c,d)=>{e.once("error",d),e.listen(a,b,c)})}catch(a){return d.lanError=a instanceof Error?a.message:String(a),e.close(),u().lan}return d.lan={server:e,port:a},u().lan}},75393:(a,b,c)=>{function d(a=process.env){let b=(a.PI_WEB_AUTH??"").trim().toLowerCase();return"1"===b||"true"===b||"on"===b||"yes"===b}c.d(b,{authEnabled:()=>d}),c(77598)}};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
globalThis.__BUILD_MANIFEST={polyfillFiles:["static/chunks/polyfills-42372ed130431b0a.js"],devFiles:[],lowPriorityFiles:["static/
|
|
1
|
+
globalThis.__BUILD_MANIFEST={polyfillFiles:["static/chunks/polyfills-42372ed130431b0a.js"],devFiles:[],lowPriorityFiles:["static/_Y3Lq0lI5RJ1tFSOnDi0L/_buildManifest.js","static/_Y3Lq0lI5RJ1tFSOnDi0L/_ssgManifest.js"],rootMainFiles:["static/chunks/webpack-3614a8337843456b.js","static/chunks/4bd1b696-93bf506b236d6248.js","static/chunks/3794-3679f1c05160977c.js","static/chunks/main-app-e9b53f0e1c6591b2.js"],rootMainFilesTree:{},pages:{"/_app":[]}};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
self.__REACT_LOADABLE_MANIFEST='{"components/AppShell.tsx -> @/components/DrawerPanel":{"id":4778,"files":["static/chunks/4673.8a5a9e6855350e34.js","static/chunks/4778.e4c9ed093a413bc4.js"]},"components/AppShell.tsx -> @/components/FileViewer":{"id":2716,"files":["static/chunks/5173.91ddb803785009f8.js","static/chunks/2716.7ad073038e94a802.js"]},"components/AppShell.tsx -> @/components/MarkdownBlock":{"id":8552,"files":["static/chunks/5173.91ddb803785009f8.js","static/chunks/8552.6bfe3e101250b20f.js"]},"components/AppShell.tsx -> @/components/ProjectPanel":{"id":4673,"files":["static/chunks/4673.8a5a9e6855350e34.js"]},"components/AppShell.tsx -> @/components/SettingsPanel":{"id":839,"files":["static/css/2959bd6b626b7ffe.css","static/chunks/839.
|
|
1
|
+
self.__REACT_LOADABLE_MANIFEST='{"components/AppShell.tsx -> @/components/DrawerPanel":{"id":4778,"files":["static/chunks/4673.8a5a9e6855350e34.js","static/chunks/4778.e4c9ed093a413bc4.js"]},"components/AppShell.tsx -> @/components/FileViewer":{"id":2716,"files":["static/chunks/5173.91ddb803785009f8.js","static/chunks/2716.7ad073038e94a802.js"]},"components/AppShell.tsx -> @/components/MarkdownBlock":{"id":8552,"files":["static/chunks/5173.91ddb803785009f8.js","static/chunks/8552.6bfe3e101250b20f.js"]},"components/AppShell.tsx -> @/components/ProjectPanel":{"id":4673,"files":["static/chunks/4673.8a5a9e6855350e34.js"]},"components/AppShell.tsx -> @/components/SettingsPanel":{"id":839,"files":["static/css/2959bd6b626b7ffe.css","static/chunks/839.d3fe337a9117c325.js"]},"components/AppShell.tsx -> @/components/TrajectoryView":{"id":618,"files":["static/css/08815507594e8b8d.css","static/chunks/618.ee5d5bf1c647e483.js"]},"components/ChatWindow.tsx -> @/components/MarkdownBlock":{"id":8552,"files":["static/chunks/5173.91ddb803785009f8.js","static/chunks/8552.6bfe3e101250b20f.js"]}}';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html lang="zh-CN"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/css/459a9ed40847a72f.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/css/6ba662805d17ffc2.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/css/7391c42e1ae617f9.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-
|
|
1
|
+
<!DOCTYPE html><html lang="zh-CN"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/css/459a9ed40847a72f.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/css/6ba662805d17ffc2.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/css/7391c42e1ae617f9.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-3614a8337843456b.js"/><script src="/_next/static/chunks/4bd1b696-93bf506b236d6248.js" async=""></script><script src="/_next/static/chunks/3794-3679f1c05160977c.js" async=""></script><script src="/_next/static/chunks/main-app-e9b53f0e1c6591b2.js" async=""></script><meta name="robots" content="noindex"/><meta name="theme-color" content="#fcfbf9" media="(prefers-color-scheme: light)"/><meta name="theme-color" content="#2e3440" media="(prefers-color-scheme: dark)"/><title>pi</title><meta name="description" content="Web UI for the pi coding agent"/><link rel="icon" href="/icon.svg?779ce17318f43f72" type="image/svg+xml" sizes="any"/><title>404: This page could not be found.</title><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/webpack-3614a8337843456b.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[7121,[],\"\"]\n3:I[4581,[],\"\"]\n4:I[484,[],\"OutletBoundary\"]\n5:\"$Sreact.suspense\"\n8:I[484,[],\"ViewportBoundary\"]\na:I[484,[],\"MetadataBoundary\"]\nc:I[7123,[],\"default\",1]\n:HL[\"/_next/static/css/459a9ed40847a72f.css\",\"style\"]\n:HL[\"/_next/static/css/6ba662805d17ffc2.css\",\"style\"]\n:HL[\"/_next/static/css/7391c42e1ae617f9.css\",\"style\"]\n7:X\n0:{\"P\":null,\"c\":[\"\",\"_not-found\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"_not-found\",{\"children\":[\"__PAGE__\",{},\"$undefined\",\"$undefined\",4608]},\"$undefined\",\"$undefined\",4608]},\"$undefined\",\"$undefined\",4624],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/459a9ed40847a72f.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"link\",\"1\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/6ba662805d17ffc2.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"link\",\"2\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/7391c42e1ae617f9.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"zh-CN\",\"suppressHydrationWarning\":true,\"children\":[\"$\",\"body\",null,{\"suppressHydrationWarning\":true,\"children\":[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L4\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@6\"}]}]]}],{},null,false,null]},null,false,\"$7\"]},null,false,null],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[\"$\",\"$L8\",null,{\"children\":\"$L9\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$La\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Lb\"}]}]}],null]}],false]],\"m\":\"$undefined\",\"G\":[\"$c\",[]],\"S\":true,\"h\":null,\"r\":\"$undefined\",\"s\":\"$undefined\",\"a\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"_Y3Lq0lI5RJ1tFSOnDi0L\"}\n7:C\n9:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"2\",{\"name\":\"theme-color\",\"content\":\"#fcfbf9\",\"media\":\"(prefers-color-scheme: light)\"}],[\"$\",\"meta\",\"3\",{\"name\":\"theme-color\",\"content\":\"#2e3440\",\"media\":\"(prefers-color-scheme: dark)\"}]]\nd:I[6869,[],\"IconMark\"]\n6:null\nb:[[\"$\",\"title\",\"0\",{\"children\":\"pi\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Web UI for the pi coding agent\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/icon.svg?779ce17318f43f72\",\"type\":\"image/svg+xml\",\"sizes\":\"any\"}],[\"$\",\"$Ld\",\"3\",{}]]\n"])</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html id="__next_error__"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-
|
|
1
|
+
<!DOCTYPE html><html id="__next_error__"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-3614a8337843456b.js"/><script src="/_next/static/chunks/4bd1b696-93bf506b236d6248.js" async=""></script><script src="/_next/static/chunks/3794-3679f1c05160977c.js" async=""></script><script src="/_next/static/chunks/main-app-e9b53f0e1c6591b2.js" async=""></script><title>500: This page couldn’t load</title><style>:root {--next-error-bg: #fff;--next-error-text: #171717;--next-error-title: #171717;--next-error-message: #171717;--next-error-digest: #666666;--next-error-btn-text: #fff;--next-error-btn-bg: #171717;--next-error-btn-border: none;--next-error-btn-secondary-text: #171717;--next-error-btn-secondary-bg: transparent;--next-error-btn-secondary-border: 1px solid rgba(0,0,0,0.08);}@media (prefers-color-scheme: dark) {:root {--next-error-bg: #0a0a0a;--next-error-text: #ededed;--next-error-title: #ededed;--next-error-message: #ededed;--next-error-digest: #a0a0a0;--next-error-btn-text: #0a0a0a;--next-error-btn-bg: #ededed;--next-error-btn-border: none;--next-error-btn-secondary-text: #ededed;--next-error-btn-secondary-bg: transparent;--next-error-btn-secondary-border: 1px solid rgba(255,255,255,0.14);}}body { margin: 0; color: var(--next-error-text); background: var(--next-error-bg); }</style><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;display:flex;align-items:center;justify-content:center"><div style="margin-top:-32px;max-width:325px;padding:32px 28px;text-align:left"><svg width="32" height="32" viewBox="-0.2 -1.5 32 32" fill="none" style="margin-bottom:24px"><path d="M16.9328 0C18.0839 0.000116771 19.1334 0.658832 19.634 1.69531L31.4299 26.1309C32.0708 27.4588 31.1036 28.9999 29.6291 29H2.00215C0.527541 29 -0.439628 27.4588 0.201371 26.1309L11.9973 1.69531C12.4979 0.658823 13.5474 7.75066e-05 14.6984 0H16.9328ZM3.59493 26H28.0363L16.9328 3H14.6984L3.59493 26ZM15.8156 19C16.9202 19.0001 17.8156 19.8955 17.8156 21C17.8156 22.1045 16.9202 22.9999 15.8156 23C14.7111 23 13.8156 22.1046 13.8156 21C13.8156 19.8954 14.7111 19 15.8156 19ZM17.3156 16.5H14.3156V8.5H17.3156V16.5Z" fill="var(--next-error-title)"></path></svg><h1 style="font-size:24px;font-weight:500;letter-spacing:-0.02em;line-height:32px;margin:0 0 12px 0;color:var(--next-error-title)">This page couldn’t load</h1><p style="font-size:14px;font-weight:400;line-height:21px;margin:0 0 20px 0;color:var(--next-error-message)">A server error occurred. Reload to try again.</p><form style="margin:0"><button type="submit" style="display:inline-flex;align-items:center;justify-content:center;height:32px;padding:0 12px;font-size:14px;font-weight:500;line-height:20px;border-radius:6px;cursor:pointer;color:var(--next-error-btn-text);background:var(--next-error-btn-bg);border:var(--next-error-btn-border)">Reload</button></form></div></div><!--$--><!--/$--><script src="/_next/static/chunks/webpack-3614a8337843456b.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[7121,[],\"\"]\n3:I[4581,[],\"\"]\n4:I[484,[],\"OutletBoundary\"]\n5:\"$Sreact.suspense\"\n8:I[484,[],\"ViewportBoundary\"]\na:I[484,[],\"MetadataBoundary\"]\nc:I[7123,[],\"default\",1]\n7:X\n0:{\"P\":null,\"c\":[\"\",\"_global-error\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"_global-error\",{\"children\":[\"__PAGE__\",{},\"$undefined\",\"$undefined\",4624]},\"$undefined\",\"$undefined\",4624]},\"$undefined\",\"$undefined\",4624],[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"html\",null,{\"id\":\"__next_error__\",\"children\":[[\"$\",\"head\",null,{\"children\":[[\"$\",\"title\",null,{\"children\":\"500: This page couldn’t load\"}],[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\":root {--next-error-bg: #fff;--next-error-text: #171717;--next-error-title: #171717;--next-error-message: #171717;--next-error-digest: #666666;--next-error-btn-text: #fff;--next-error-btn-bg: #171717;--next-error-btn-border: none;--next-error-btn-secondary-text: #171717;--next-error-btn-secondary-bg: transparent;--next-error-btn-secondary-border: 1px solid rgba(0,0,0,0.08);}@media (prefers-color-scheme: dark) {:root {--next-error-bg: #0a0a0a;--next-error-text: #ededed;--next-error-title: #ededed;--next-error-message: #ededed;--next-error-digest: #a0a0a0;--next-error-btn-text: #0a0a0a;--next-error-btn-bg: #ededed;--next-error-btn-border: none;--next-error-btn-secondary-text: #ededed;--next-error-btn-secondary-bg: transparent;--next-error-btn-secondary-border: 1px solid rgba(255,255,255,0.14);}}body { margin: 0; color: var(--next-error-text); background: var(--next-error-bg); }\"}}]]}],[\"$\",\"body\",null,{\"children\":[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"display\":\"flex\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"style\":{\"marginTop\":\"-32px\",\"maxWidth\":\"325px\",\"padding\":\"32px 28px\",\"textAlign\":\"left\"},\"children\":[[\"$\",\"svg\",null,{\"width\":\"32\",\"height\":\"32\",\"viewBox\":\"-0.2 -1.5 32 32\",\"fill\":\"none\",\"style\":{\"marginBottom\":\"24px\"},\"children\":[\"$\",\"path\",null,{\"d\":\"M16.9328 0C18.0839 0.000116771 19.1334 0.658832 19.634 1.69531L31.4299 26.1309C32.0708 27.4588 31.1036 28.9999 29.6291 29H2.00215C0.527541 29 -0.439628 27.4588 0.201371 26.1309L11.9973 1.69531C12.4979 0.658823 13.5474 7.75066e-05 14.6984 0H16.9328ZM3.59493 26H28.0363L16.9328 3H14.6984L3.59493 26ZM15.8156 19C16.9202 19.0001 17.8156 19.8955 17.8156 21C17.8156 22.1045 16.9202 22.9999 15.8156 23C14.7111 23 13.8156 22.1046 13.8156 21C13.8156 19.8954 14.7111 19 15.8156 19ZM17.3156 16.5H14.3156V8.5H17.3156V16.5Z\",\"fill\":\"var(--next-error-title)\"}]}],[\"$\",\"h1\",null,{\"style\":{\"fontSize\":\"24px\",\"fontWeight\":500,\"letterSpacing\":\"-0.02em\",\"lineHeight\":\"32px\",\"margin\":\"0 0 12px 0\",\"color\":\"var(--next-error-title)\"},\"children\":\"This page couldn’t load\"}],[\"$\",\"p\",null,{\"style\":{\"fontSize\":\"14px\",\"fontWeight\":400,\"lineHeight\":\"21px\",\"margin\":\"0 0 20px 0\",\"color\":\"var(--next-error-message)\"},\"children\":\"A server error occurred. Reload to try again.\"}],[\"$\",\"form\",null,{\"style\":{\"margin\":0},\"children\":[\"$\",\"button\",null,{\"type\":\"submit\",\"style\":{\"display\":\"inline-flex\",\"alignItems\":\"center\",\"justifyContent\":\"center\",\"height\":\"32px\",\"padding\":\"0 12px\",\"fontSize\":\"14px\",\"fontWeight\":500,\"lineHeight\":\"20px\",\"borderRadius\":\"6px\",\"cursor\":\"pointer\",\"color\":\"var(--next-error-btn-text)\",\"background\":\"var(--next-error-btn-bg)\",\"border\":\"var(--next-error-btn-border)\"},\"children\":\"Reload\"}]}]]}]}]}]]}],null,[\"$\",\"$L4\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@6\"}]}]]}],{},null,false,null]},null,false,\"$7\"]},null,false,\"$7\"],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$L8\",null,{\"children\":\"$L9\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$La\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Lb\"}]}]}],null]}],false]],\"m\":\"$undefined\",\"G\":[\"$c\",[]],\"S\":true,\"h\":null,\"r\":\"$undefined\",\"s\":\"$undefined\",\"a\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"_Y3Lq0lI5RJ1tFSOnDi0L\"}\n7:C\n9:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n6:null\nb:[]\n"])</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"node":{},"edge":{},"encryptionKey":"
|
|
1
|
+
{"node":{},"edge":{},"encryptionKey":"rTzHSqdWBY+W9wtrhPKGZpuL+lXgo1AIkb//uzw+fjw="}
|