@buzzni/saycode-cli 0.9.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.mjs +269 -103
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createInterface } from "node:readline";
3
3
  import { homedir, tmpdir, platform, totalmem, freemem, cpus, userInfo, hostname as hostname$1 } from "node:os";
4
- import fs, { readFileSync, mkdirSync, writeFileSync, rmSync, chmodSync, constants as constants$3, existsSync, realpathSync, createWriteStream, appendFileSync, openSync, fstatSync, readSync, closeSync, accessSync, statSync } from "node:fs";
4
+ import fs, { readFileSync, mkdirSync, writeFileSync, rmSync, chmodSync, constants as constants$3, appendFileSync, existsSync, realpathSync, createWriteStream, openSync, fstatSync, readSync, closeSync, accessSync, statSync } from "node:fs";
5
5
  import path$1, { dirname, join, basename, extname, delimiter, win32, resolve, sep, relative, isAbsolute } from "node:path";
6
6
  import { createHash, randomUUID, randomBytes, generateKeyPairSync, sign, createHmac, timingSafeEqual, createPublicKey, verify } from "node:crypto";
7
7
  import require$$0$5, { Buffer as Buffer$1 } from "buffer";
@@ -49,7 +49,7 @@ function _mergeNamespaces(n, m) {
49
49
  }
50
50
  return Object.freeze(Object.defineProperty(n, Symbol.toStringTag, { value: "Module" }));
51
51
  }
52
- const version$3 = "0.9.0";
52
+ const version$3 = "0.9.1";
53
53
  const manifest = {
54
54
  version: version$3
55
55
  };
@@ -427,9 +427,6 @@ const chatWorkKo = {
427
427
  "trialStarter.tips.title": "연동하여 내 메일 문서를 채팅에서 작업해보세요.",
428
428
  "trialStarter.upload.action": "내 파일 올리기",
429
429
  "trialStarter.upload.hint": "워드·엑셀·PDF 그대로",
430
- "chatWork.replaceTitle": "예시로 바꿀까요?",
431
- "chatWork.replaceBody": "작성한 내용은 예시로 바뀌고, 내 파일은 그대로 남아요.",
432
- "chatWork.replace": "예시로 바꾸기",
433
430
  "chatWork.cancel": "취소",
434
431
  "chatWork.preparing": "샘플 준비 중…",
435
432
  "chatWork.sampleFailed": "샘플을 준비하지 못했어요. 다시 선택하거나 내 파일을 올려 주세요.",
@@ -1060,6 +1057,10 @@ const organizationStartKo = {
1060
1057
  "organizationStart.diagnostic.action.publicMissing": "조직 관리자에게 공용 인증 등록을 확인해 달라고 요청한 뒤 다시 연결해주세요.",
1061
1058
  "organizationStart.diagnostic.reason.publicApply": "회사 공용 AI 인증을 이 컴퓨터에 적용하지 못했어요.",
1062
1059
  "organizationStart.diagnostic.action.publicApply": "네트워크 연결을 확인하고 다시 연결해주세요. 계속 실패하면 진단 정보를 조직 관리자에게 전달해주세요.",
1060
+ "organizationStart.diagnostic.reason.notDedicated": "이 PC가 이 계정의 조직 전용 PC로 등록되어 있지 않아요.",
1061
+ "organizationStart.diagnostic.action.notDedicated": "조직 관리자에게 조직 관리 → PC에서 이 PC를 이 계정의 전용 PC로 다시 등록해 달라고 요청해주세요.",
1062
+ "organizationStart.diagnostic.reason.registrationChanged": "이 PC의 조직 등록이 바뀌었거나 삭제되어 이 계정으로 연결할 수 없어요.",
1063
+ "organizationStart.diagnostic.action.registrationChanged": "조직 관리자에게 조직 관리 → PC에서 이 PC의 등록을 확인해 달라고 요청한 뒤 다시 시도해주세요.",
1063
1064
  "organizationStart.diagnostic.reason.publicVerify": "공용 인증을 적용했지만 AI 인증 사용을 확인하지 못했어요.",
1064
1065
  "organizationStart.diagnostic.action.publicVerify": "조직 관리자에게 최신 공용 인증 복구를 요청한 뒤 다시 연결해주세요."
1065
1066
  };
@@ -1297,6 +1298,8 @@ const chatSchedulesKo = {
1297
1298
  "chatSchedules.navigation": "예약",
1298
1299
  "chatSchedules.new": "새 예약",
1299
1300
  "chatSchedules.edit": "편집",
1301
+ "chatSchedules.partialRead": "일부 예약을 확인하지 못했어요. 다시 확인해 주세요.",
1302
+ "chatSchedules.resumeDraft": "이어서 작성",
1300
1303
  "chatSchedules.retry": "다시 확인",
1301
1304
  "chatSchedules.loading": "예약 작업을 불러오는 중…",
1302
1305
  "chatSchedules.loadError": "예약을 불러오지 못했습니다. 다시 확인해 주세요.",
@@ -1677,7 +1680,7 @@ const machineUsageClaudeKo = {
1677
1680
  "machineUsage.coverageUnknown": "모델 한도 미확인",
1678
1681
  "machineUsage.notObserved": "아직 확인되지 않음",
1679
1682
  "machineUsage.scopeDiagnosis": "사용량 권한 진단 필요",
1680
- "machineUsage.sourceOrganizationCollector": "조직 수집기",
1683
+ "machineUsage.organizationAccount": "조직계정",
1681
1684
  "machineUsage.probeTitle": "개인 사용량 확인",
1682
1685
  "machineUsage.probeCentral": "조직 사용량은 자동으로 확인해요. 여기서는 켜거나 새로고침할 수 없어요.",
1683
1686
  "machineUsage.probeUpdateRequired": "사용량을 확인하려면 작업PC의 도구 버전과 계정 연결을 확인해 주세요.",
@@ -2672,6 +2675,7 @@ const personalChatsKo = {
2672
2675
  "personalChats.automationSaved": "자동화 설정이 저장되었습니다",
2673
2676
  "personalChats.automationDeleted": "자동화가 삭제되었습니다",
2674
2677
  "personalChats.title": "내 채팅",
2678
+ "personalChats.compose": "새 채팅 작성",
2675
2679
  "personalChats.newChat": "새 대화",
2676
2680
  "personalChats.searchPlaceholder": "채팅 검색",
2677
2681
  "personalChats.sortRecent": "최신 작업순으로 정렬",
@@ -2977,7 +2981,33 @@ const collaborationMachineKo = {
2977
2981
  "collaboration.pcOffline": "작업PC가 오프라인입니다. 읽기 권한이 있는 기존 대화는 볼 수 있지만 새 실행에는 PC 연결이 필요합니다.",
2978
2982
  "collaboration.pcUnavailable": "작업PC 정보를 확인하지 못했습니다. 기존 대화 열람과 새 실행 권한은 다릅니다. 소유자에게 PC 연결·접근 설정을 확인해 주세요.",
2979
2983
  "collaboration.dedicatedPcUnavailable": "전용 PC에서는 함께 작업할 수 없습니다.",
2980
- "collaboration.personalPcUnavailable": "개인 PC에서는 함께 작업할 수 없습니다."
2984
+ "collaboration.personalPcUnavailable": "개인 PC에서는 함께 작업할 수 없습니다.",
2985
+ "machineSharing.title": "PC 공유 설정",
2986
+ "machineSharing.share": "공용으로 변경",
2987
+ "machineSharing.dedicated": "전용으로 변경",
2988
+ "machineSharing.save": "저장",
2989
+ "machineSharing.saving": "저장 중…",
2990
+ "machineSharing.accessHeading": "PC 사용 가능 사용자",
2991
+ "machineSharing.shareHelp": "공용으로 변경하면 우선 나만 사용할 수 있습니다.",
2992
+ "machineSharing.selectedHelp": "허용한 사용자는 이 PC에서 작업을 실행할 수 있습니다.",
2993
+ "machineSharing.confirmInvite": "PC 접근 권한을 추가하고 초대할까요?",
2994
+ "machineSharing.confirmInviteHelp": "선택한 사용자가 이 PC를 사용할 수 있게 됩니다. 프로젝트에는 초대 수락 후 참여합니다.",
2995
+ "machineSharing.grantAndInvite": "권한 추가 후 초대",
2996
+ "machineSharing.accessGranted": "PC 접근 권한은 추가됐습니다. 실패한 프로젝트 초대는 다시 시도해 주세요.",
2997
+ "machineSharing.stateChanged": "PC 설정이 변경됐습니다. 다시 확인해 주세요.",
2998
+ "machineSharing.aiAuthRequired": "이 PC의 AI 인증을 공용으로 전환할 수 없습니다.",
2999
+ "machineSharing.projectConflict": "함께 작업 중인 사용자가 있어 접근 권한을 줄일 수 없습니다.",
3000
+ "machineSharing.membersUnavailable": "참여자를 확인하지 못했습니다. 잠시 후 다시 시도해 주세요.",
3001
+ "machineSharing.runtimeUnavailable": "PC 연결을 확인한 뒤 다시 시도해 주세요.",
3002
+ "machineSharing.ownerRequired": "PC 소유자나 머신 관리자에게 접근 권한 추가를 요청해 주세요.",
3003
+ "machineSharing.serverUnavailable": "공유 설정을 사용할 수 없습니다. 서버 업데이트를 확인해 주세요.",
3004
+ "machineSharing.requestFailed": "공유 설정 결과를 확인하지 못했습니다. 다시 확인해 주세요.",
3005
+ "machineSharing.loadFailed": "공유 설정을 불러오지 못했습니다.",
3006
+ "machineSharing.retry": "다시 확인",
3007
+ "machineSharing.cancel": "취소",
3008
+ "machineSharing.close": "닫기",
3009
+ "machineSharing.allMembers": "전체 조직 멤버",
3010
+ "machineSharing.convertFirst": "공용으로 변경한 뒤 함께 작업할 수 있습니다."
2981
3011
  };
2982
3012
  const collaborationKo = {
2983
3013
  ...collaborationMachineKo,
@@ -3276,6 +3306,8 @@ const newSessionProfileKo = {
3276
3306
  "newSession.profile.none": "프로필 없음",
3277
3307
  "newSession.profile.executionSettings": "실행 설정",
3278
3308
  "newSession.profile.editSettings": "편집",
3309
+ "newSession.profile.saving": "저장 중…",
3310
+ "newSession.profile.temporarySelection": "현재 환경에 맞춰 표시 중이며, AI·모델·강도를 직접 바꾸기 전까지 저장된 선택은 유지됩니다.",
3279
3311
  "newSession.profile.saveChanges": "변경사항 저장",
3280
3312
  "newSession.profile.instructionsField": "추가 지시문",
3281
3313
  "newSession.profile.badgeIconField": "표식 아이콘",
@@ -4048,14 +4080,12 @@ const agentBrowserConsoleKo = {
4048
4080
  "browserPanel.agentBrowserUnauthorized": "로그인이 만료되었습니다. 다시 로그인한 뒤 콘솔을 여세요.",
4049
4081
  "browserPanel.agentBrowserExpired": "콘솔 접근 권한이 만료되었습니다. AI 브라우저 작업 콘솔을 다시 여세요.",
4050
4082
  "browserPanel.agentBrowserFailed": "AI 브라우저 콘솔 권한을 받지 못했습니다. 잠시 뒤 다시 시도하세요.",
4051
- "agentBrowser.chat.showNotice": "AI 브라우저 안내 보이기",
4052
- "agentBrowser.chat.showNoticeHint": "대화 상단에 브라우저 콘솔을 여는 안내를 보여 줍니다.",
4053
- "agentBrowser.chat.title": "AI 브라우저",
4083
+ "agentBrowser.chat.showNotice": "AI 브라우저 버튼 보이기",
4084
+ "agentBrowser.chat.showNoticeHint": "대화 오른쪽 위에 AI 브라우저 열기 버튼을 보여 줍니다.",
4054
4085
  "agentBrowser.chat.notice": "로그인이나 승인이 필요하면 AI 브라우저 콘솔에서 직접 처리할 수 있어요.",
4055
4086
  "agentBrowser.chat.ownersBrowser": "이 대화의 브라우저 작업은 대화를 만든 사람의 로그인으로 실행됩니다.",
4056
4087
  "agentBrowser.chat.ownersBrowserNamed": "이 대화의 브라우저 작업은 {name}님의 로그인으로 실행됩니다.",
4057
- "agentBrowser.chat.open": "브라우저 콘솔 열기",
4058
- "agentBrowser.chat.dismiss": "AI 브라우저 안내 닫기",
4088
+ "agentBrowser.chat.open": "AI 브라우저 열기",
4059
4089
  "agentBrowser.chat.modeMismatch": "작업PC의 AI 브라우저 설정이 공용·전용 구분과 맞지 않아 브라우저를 사용할 수 없어요. 관리자에게 작업PC 설정 확인을 요청해 주세요.",
4060
4090
  "agentBrowser.confirm.title": "다른 사람의 로그인으로 실행됩니다",
4061
4091
  "agentBrowser.confirm.titleNamed": "{name}님의 로그인으로 실행됩니다",
@@ -4374,7 +4404,7 @@ const designGuideComponentKo = {
4374
4404
  "designGuide.components.tabs.rule2": "선택된 탭과 hover는 accent 면으로 구분합니다. 파란 밑줄을 쓰지 않습니다.",
4375
4405
  "designGuide.components.tabs.rule3": "모든 탭에 닫기 버튼(24px)을 둡니다. 탭이 많으면 줄을 바꾸지 않고 가로로 스크롤합니다.",
4376
4406
  "designGuide.components.tabs.rule4": "새 탭 버튼은 탭 행 끝에 28px 아이콘 버튼으로 둡니다. 중앙 대화 탭 행은 새 대화 작성 아이콘(SquarePen), 우측 도구 탭 행은 추가 메뉴 아이콘(…)을 씁니다. 방향키로 탭 사이를 옮길 수 있습니다.",
4377
- "designGuide.components.tabs.rule5": "홈 첫 화면의 모드 탭만 36px 알약 모양입니다. 탭은 Chat과 Develop이고, Build 탭은 조직이 buzzni일 때만 그 사이에 나타납니다. 이 탭과 사이드바 Chat/Project 탭은 선택 표시가 260ms 동안 옮겨 갑니다.",
4407
+ "designGuide.components.tabs.rule5": "Project 화면에는 모든 사용자에게 Build·Develop 36px 알약 탭을 표시하고 선택 표시는 260ms 동안 이동합니다. Chat은 사이드바 메뉴에서 별도의 입력 화면으로 엽니다.",
4378
4408
  "designGuide.components.tabs.rule6": "중앙 대화 탭과 우측 도구 탭은 끌어서 순서를 바꿀 수 있습니다. Cmd+W는 마지막으로 누르거나 포커스한 탭을 닫기 버튼과 같은 방식으로 닫고, 마지막 탭이어도 창은 닫지 않습니다. 닫기 버튼 툴팁에 이 단축키를 적습니다.",
4379
4409
  "designGuide.components.tabs.note": "작업 탭 행은 WorkspaceHost 안에서 작업 상태와 함께 그려져 따로 렌더할 수 없습니다. 같은 클래스로 모양만 보여 주고, 2단계에서 탭 행을 부품으로 나누면 실물로 바꿉니다. 지금 탭 모서리는 7px, 닫기 버튼은 5px이라 모서리 단계와 다릅니다. 우측 도구 탭(.workspace-tool-tab)은 값은 같지만 클래스가 따로 있어 2단계에서 한 부품으로 묶습니다.",
4380
4410
  "designGuide.components.listRows": "목록 행",
@@ -4383,7 +4413,7 @@ const designGuideComponentKo = {
4383
4413
  "designGuide.components.listRows.rule2": "행 끝에는 추가 메뉴(…)와 고정 버튼만 둡니다. 이름 변경, 보관, 복사, 삭제는 추가 메뉴 안에 있습니다. 두 버튼은 hover나 키보드 포커스 때만 보이고, 숨어 있을 때는 제목 자리를 차지하지 않습니다. 대화 목록(Project, Chat)은 행 앞 대화 아이콘을 두지 않고, Chat 목록에서 고정된 행의 핀은 늘 보여 줍니다.",
4384
4414
  "designGuide.components.listRows.rule3": "행 제목은 한 줄로 줄이고, 전체 이름은 hover 툴팁으로 보여 줍니다.",
4385
4415
  "designGuide.components.listRows.rule4": "끌어서 순서를 바꿀 때는 놓일 자리에 2px 브랜드색 선을 그리고, 실제로 놓이는 자리와 맞춥니다.",
4386
- "designGuide.components.listRows.rule5": "사이드바 맨 위 주요 메뉴(Saycode 홈, 작업보드, 외부 연동)는 44px 행, 15px 글자, 18px 아이콘이고, 현재 목적지는 브랜드색을 옅게 섞은 배경으로 표시합니다.",
4416
+ "designGuide.components.listRows.rule5": "사이드바 상단 주요 메뉴(Chat, Project, 작업보드, 예약, 외부 연동)는 44px 행, 15px 글자, 18px 아이콘을 사용합니다. 작업보드와 예약은 표시 설정에 따라 나타납니다. 호버·선택은 옅은 브랜드색 배경으로 구분하고, Chat·Project 상세에서는 상단 메뉴 대신 현재 목록 항목만 선택 표시합니다.",
4387
4417
  "designGuide.components.toasts": "전역 알림",
4388
4418
  "designGuide.components.toasts.intro": "어느 화면에서 일어난 일이든 창 위쪽 가운데에 띄우는 알림입니다. 버튼을 누르면 실제 알림이 뜹니다.",
4389
4419
  "designGuide.components.toasts.rule1": "모든 토스트는 공통 FloatingNotice와 이 실제 예제를 사용합니다. 창 상단 중앙에 표시하고 빈 text로 숨겨 퇴장 효과를 유지합니다.",
@@ -4912,6 +4942,9 @@ const machineSetupKo = {
4912
4942
  "machineSetup.installTitle": "CLI 설치",
4913
4943
  "machineSetup.cloudTitle": "Saycode 클라우드",
4914
4944
  "machineSetup.standaloneTitle": "이 컴퓨터 연결",
4945
+ "machineSetup.selfHostTitle": "이 서버에 작업PC 연결",
4946
+ "machineSetup.pairingCode": "연결 코드",
4947
+ "machineSetup.selfHostHelp": "새 작업PC에서 로그인 명령을 실행하면 연결 코드가 나옵니다. 서버에서 그 코드를 승인한 뒤 새 작업PC에서 데몬을 시작하세요.",
4915
4948
  "machineSetup.serverAddress": "서버 주소",
4916
4949
  "machineSetup.authHelp": "happy auth login을 실행하면 모바일 앱 또는 웹 URL을 통해 작업PC를 등록할 수 있습니다.",
4917
4950
  "machineSetup.organizationHelp": "조직 전용·공용 PC는 아래에서 발급한 명령을 새 작업PC에서 실행해 등록하세요."
@@ -5058,9 +5091,7 @@ const ko = {
5058
5091
  "networkDataSaver.deferred.memory": "Memory Layer 대화 백필",
5059
5092
  "networkDataSaver.deferred.gitPr": "백그라운드 Git 및 PR 새로고침",
5060
5093
  "happyCliUpdate.title": "Aplus CLI 업데이트",
5061
- "happyCliUpdate.checkTitle": "Aplus CLI 업데이트",
5062
5094
  "happyCliUpdate.managerTitle": "Aplus CLI 업데이트",
5063
- "happyCliUpdate.impact": "업데이트 중 머신 연결이 잠시 끊길 수 있습니다.",
5064
5095
  "happyCliUpdate.update": "업데이트",
5065
5096
  "happyCliUpdate.updating": "업데이트 중…",
5066
5097
  "happyCliUpdate.updated": "업데이트됨",
@@ -8261,6 +8292,21 @@ In a chat
8261
8292
  /model · /effort · /voice [path] · /detach · /exit live chat commands
8262
8293
 
8263
8294
  Leaving never stops a remote session — it keeps running on the machine.`;
8295
+ const record$i = (value2) => !!value2 && typeof value2 === "object" && !Array.isArray(value2);
8296
+ const ids = (value2) => Array.isArray(value2) && value2.length <= 1e3 && value2.every((id2) => typeof id2 === "string" && id2.trim().length > 0);
8297
+ function parseMachineSharing(value2) {
8298
+ if (!record$i(value2) || !record$i(value2.machine)) throw new Error("Invalid machine sharing response");
8299
+ const m = value2.machine;
8300
+ if (typeof value2.revision !== "string" || !value2.revision || !["canShare", "canMakeDedicated", "canManageAccess"].every((key) => typeof value2[key] === "boolean") || !["machineId", "ownerId", "companyId", "infraMode"].every((key) => typeof m[key] === "string" && !!m[key]) || !["dedicated", "shared"].includes(String(m.type)) || !ids(m.accessList) || m.accessList.length === 0 || m.accessList.includes("*") && m.accessList.length !== 1 || m.assignedUserId != null && typeof m.assignedUserId !== "string" || value2.missingUserIds !== void 0 && !ids(value2.missingUserIds)) throw new Error("Invalid machine sharing response");
8301
+ return {
8302
+ machine: m,
8303
+ revision: value2.revision,
8304
+ canShare: value2.canShare,
8305
+ canMakeDedicated: value2.canMakeDedicated,
8306
+ canManageAccess: value2.canManageAccess,
8307
+ missingUserIds: value2.missingUserIds ?? []
8308
+ };
8309
+ }
8264
8310
  const BASE64_PATTERN$3 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
8265
8311
  function versionedAutomationBase64(value2, maxBytes, exactBytes) {
8266
8312
  if (typeof value2 !== "string" || !value2 || value2.length > Math.ceil(maxBytes / 3) * 4 || !BASE64_PATTERN$3.test(value2)) {
@@ -13387,14 +13433,14 @@ const $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def)
13387
13433
  return `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
13388
13434
  };
13389
13435
  doc.write(`const input = payload.value;`);
13390
- const ids = /* @__PURE__ */ Object.create(null);
13436
+ const ids2 = /* @__PURE__ */ Object.create(null);
13391
13437
  let counter = 0;
13392
13438
  for (const key of normalized.keys) {
13393
- ids[key] = `key_${counter++}`;
13439
+ ids2[key] = `key_${counter++}`;
13394
13440
  }
13395
13441
  doc.write(`const newResult = {};`);
13396
13442
  for (const key of normalized.keys) {
13397
- const id2 = ids[key];
13443
+ const id2 = ids2[key];
13398
13444
  const k = esc(key);
13399
13445
  doc.write(`const ${id2} = ${parseStr(key)};`);
13400
13446
  doc.write(`
@@ -29138,25 +29184,25 @@ const MAX_CACHED_BODY_AGE_MS = 10 * 6e4;
29138
29184
  const SESSION_ROW_CACHE_IDLE_MS = 10 * 6e4;
29139
29185
  const rowsByScope = /* @__PURE__ */ new Map();
29140
29186
  const versionUnsupportedUntilByScope = /* @__PURE__ */ new Map();
29141
- async function lookupSessionRowsIncremental(ids, deps) {
29142
- if (ids.length === 0) return [];
29143
- const remember = (rows2) => rememberRows(deps.scope, ids, rows2, deps.now());
29187
+ async function lookupSessionRowsIncremental(ids2, deps) {
29188
+ if (ids2.length === 0) return [];
29189
+ const remember = (rows2) => rememberRows(deps.scope, ids2, rows2, deps.now());
29144
29190
  if (deps.now() < (versionUnsupportedUntilByScope.get(deps.scope) ?? 0)) {
29145
- return remember(stamp(await deps.fetchFull(ids), deps.now()));
29191
+ return remember(stamp(await deps.fetchFull(ids2), deps.now()));
29146
29192
  }
29147
- const versions = await deps.fetchVersions(ids);
29193
+ const versions = await deps.fetchVersions(ids2);
29148
29194
  if (versions === null) {
29149
29195
  {
29150
29196
  versionUnsupportedUntilByScope.set(deps.scope, deps.now() + VERSION_PROJECTION_RETRY_MS);
29151
29197
  }
29152
- return remember(stamp(await deps.fetchFull(ids), deps.now()));
29198
+ return remember(stamp(await deps.fetchFull(ids2), deps.now()));
29153
29199
  }
29154
29200
  if (versions.some(isFullRow)) {
29155
29201
  return remember(stamp(versions.filter(isFullRow), deps.now()));
29156
29202
  }
29157
29203
  const cached2 = rowsByScope.get(deps.scope);
29158
29204
  const seenAt = deps.now();
29159
- const requested = new Set(ids);
29205
+ const requested = new Set(ids2);
29160
29206
  const plan = versions.flatMap((row2) => {
29161
29207
  const id2 = row2 && typeof row2.id === "string" ? row2.id : null;
29162
29208
  if (!id2 || !requested.has(id2)) return [];
@@ -29224,7 +29270,9 @@ function parseVersionRow(row2) {
29224
29270
  const machineRegistryCache = /* @__PURE__ */ new Map();
29225
29271
  const MACHINE_REGISTRY_CACHE_TTL_MS = 10 * 6e4;
29226
29272
  const MACHINE_REGISTRY_CACHE_MAX_ENTRIES = 32;
29273
+ let machineRegistryCacheGeneration = 0;
29227
29274
  function clearMachineRegistryCache() {
29275
+ machineRegistryCacheGeneration++;
29228
29276
  machineRegistryCache.clear();
29229
29277
  }
29230
29278
  const TRANSCRIPTION_PATH = "/api/transcriptions";
@@ -30497,6 +30545,18 @@ class ApiClient {
30497
30545
  );
30498
30546
  return parseProjectMembersPayload(data);
30499
30547
  }
30548
+ async getMachineSharing(machineId, userIds = []) {
30549
+ const query = new URLSearchParams({ machineId });
30550
+ for (const id2 of userIds) query.append("userId", id2);
30551
+ return parseMachineSharing(await this.request(`/api/machines/sharing?${query}`, { boundary: "api" }));
30552
+ }
30553
+ async changeMachineSharing(machineId, command) {
30554
+ try {
30555
+ return parseMachineSharing(await this.request("/api/machines/sharing", { boundary: "api", method: "POST", body: JSON.stringify({ machineId, ...command }), timeoutMs: 35e3 }));
30556
+ } finally {
30557
+ clearMachineRegistryCache();
30558
+ }
30559
+ }
30500
30560
  async getCompanyMemberDirectoryPage(companyId, cursor) {
30501
30561
  const data = await this.request(buildCompanyMemberDirectoryPath(companyId, cursor), { boundary: "api" });
30502
30562
  return parseCompanyMemberDirectoryPage(data);
@@ -30925,6 +30985,7 @@ class ApiClient {
30925
30985
  if (machineIds.length === 0) return {};
30926
30986
  const cacheKey = `${this.config.apiToken ?? ""}\0${[...machineIds].sort().join(",")}`;
30927
30987
  const now = Date.now();
30988
+ const generation = machineRegistryCacheGeneration;
30928
30989
  const cached2 = machineRegistryCache.get(cacheKey);
30929
30990
  if (cached2 && now - cached2.at < MACHINE_REGISTRY_CACHE_TTL_MS) return cached2.value;
30930
30991
  try {
@@ -30934,7 +30995,7 @@ class ApiClient {
30934
30995
  );
30935
30996
  const value2 = indexMachineRegistry(Array.isArray(data) ? data : data.machines ?? []);
30936
30997
  if (machineRegistryCache.size >= MACHINE_REGISTRY_CACHE_MAX_ENTRIES) machineRegistryCache.clear();
30937
- machineRegistryCache.set(cacheKey, { at: now, value: value2 });
30998
+ if (generation === machineRegistryCacheGeneration) machineRegistryCache.set(cacheKey, { at: now, value: value2 });
30938
30999
  return value2;
30939
31000
  } catch (error) {
30940
31001
  console.warn("[machines] registry enrichment failed; falling back to hostnames", error);
@@ -31114,37 +31175,37 @@ class ApiClient {
31114
31175
  hasNext: data.hasNext === true
31115
31176
  };
31116
31177
  }
31117
- async lookupSessionSeqs(ids, tokenOverride) {
31118
- if (ids.length === 0) return [];
31178
+ async lookupSessionSeqs(ids2, tokenOverride) {
31179
+ if (ids2.length === 0) return [];
31119
31180
  const data = await this.request("/v2/sessions/lookup", {
31120
31181
  method: "POST",
31121
31182
  boundary: "sync",
31122
31183
  tokenOverride,
31123
- body: JSON.stringify({ ids, projection: "seq" })
31184
+ body: JSON.stringify({ ids: ids2, projection: "seq" })
31124
31185
  });
31125
- const requested = new Set(ids);
31186
+ const requested = new Set(ids2);
31126
31187
  return (data.sessions ?? []).flatMap((row2) => row2 && typeof row2.id === "string" && requested.has(row2.id) && typeof row2.seq === "number" && Number.isSafeInteger(row2.seq) && row2.seq >= 0 ? [{ id: row2.id, seq: row2.seq }] : []);
31127
31188
  }
31128
- async lookupApiSessions(ids, tokenOverride) {
31129
- if (ids.length === 0) return [];
31189
+ async lookupApiSessions(ids2, tokenOverride) {
31190
+ if (ids2.length === 0) return [];
31130
31191
  const data = await this.request("/v2/sessions/lookup", {
31131
31192
  method: "POST",
31132
31193
  boundary: "sync",
31133
31194
  tokenOverride,
31134
- body: JSON.stringify({ ids })
31195
+ body: JSON.stringify({ ids: ids2 })
31135
31196
  });
31136
31197
  return data.sessions ?? [];
31137
31198
  }
31138
- async lookupSessions(candidateKeys, ids, tokenOverride, accountPrivateKey = null) {
31199
+ async lookupSessions(candidateKeys, ids2, tokenOverride, accountPrivateKey = null) {
31139
31200
  const boundaryGeneration2 = sessionDekRegistryGeneration();
31140
- const rows = await this.lookupApiSessions(ids, tokenOverride);
31201
+ const rows = await this.lookupApiSessions(ids2, tokenOverride);
31141
31202
  await preDecryptSessionHeaders(rows, accountPrivateKey, boundaryGeneration2);
31142
31203
  return rows.map((row2) => apiSessionToSession(row2, candidateKeys));
31143
31204
  }
31144
31205
  /** Runtime poll only: bodies are refetched only when a version or key presence moved. */
31145
- async lookupSessionsForRuntime(candidateKeys, ids, tokenOverride, accountPrivateKey = null) {
31206
+ async lookupSessionsForRuntime(candidateKeys, ids2, tokenOverride, accountPrivateKey = null) {
31146
31207
  const boundaryGeneration2 = sessionDekRegistryGeneration();
31147
- const rows = await lookupSessionRowsIncremental(ids, {
31208
+ const rows = await lookupSessionRowsIncremental(ids2, {
31148
31209
  scope: `${this.config.syncBaseUrl}\0${tokenOverride ?? this.config.syncToken ?? ""}`,
31149
31210
  fetchVersions: (chunk) => this.request("/v2/sessions/lookup", {
31150
31211
  method: "POST",
@@ -32542,8 +32603,8 @@ class CliRest {
32542
32603
  return data.sessions ?? [];
32543
32604
  }
32544
32605
  /** Rows for the given ids, however old: the list above stops at the latest 150. */
32545
- async lookupSessions(ids) {
32546
- const data = await this.request("/v2/sessions/lookup", { method: "POST", body: JSON.stringify({ ids }) });
32606
+ async lookupSessions(ids2) {
32607
+ const data = await this.request("/v2/sessions/lookup", { method: "POST", body: JSON.stringify({ ids: ids2 }) });
32547
32608
  return data.sessions ?? [];
32548
32609
  }
32549
32610
  async recentMessages(sessionId, limit, afterSeq) {
@@ -40428,8 +40489,8 @@ const processEvidence = (error) => {
40428
40489
  const { code, stderr } = error ?? {};
40429
40490
  if (typeof code === "string" && /^[A-Z][A-Z0-9_]{1,31}$/.test(code)) return `PowerShell could not start: ${code}`;
40430
40491
  if (typeof code !== "number") return "";
40431
- const ids = [...String(stderr ?? "").replace(/_x[0-9A-Fa-f]{4}_/g, " ").matchAll(/FullyQualifiedErrorId\s*:\s*([A-Za-z][\w.,-]{0,79})/g)].map((match) => match[1]).slice(0, 3);
40432
- return [`PowerShell exit ${code}`, ...ids].join(", ");
40492
+ const ids2 = [...String(stderr ?? "").replace(/_x[0-9A-Fa-f]{4}_/g, " ").matchAll(/FullyQualifiedErrorId\s*:\s*([A-Za-z][\w.,-]{0,79})/g)].map((match) => match[1]).slice(0, 3);
40493
+ return [`PowerShell exit ${code}`, ...ids2].join(", ");
40433
40494
  };
40434
40495
  async function runAclProtection(run2, mode2) {
40435
40496
  let reason = "";
@@ -40603,12 +40664,23 @@ async function serverLockHolder(layout) {
40603
40664
  const pid = typeof holder?.pid === "number" ? holder.pid : null;
40604
40665
  return pid !== null && processIsAlive(pid) ? pid : null;
40605
40666
  }
40667
+ function serverLogWriter(layout, name) {
40668
+ const file = join(layout.logsDir, `${name}.log`);
40669
+ return (line2) => {
40670
+ try {
40671
+ mkdirSync(layout.logsDir, { recursive: true, mode: 448 });
40672
+ appendFileSync(file, `${(/* @__PURE__ */ new Date()).toISOString()} ${line2}
40673
+ `, { mode: 384 });
40674
+ } catch {
40675
+ }
40676
+ };
40677
+ }
40606
40678
  const happyCliPackageName = "@buzzni/happy-cli";
40607
- const happyCliVersion = "1.1.10-aplus.311";
40608
- const happyCliTag = "happy-cli-v1.1.10-aplus.311";
40609
- const vendorCommit = "db95378e2a1e0da2b83c94a834011f7900f2caa3";
40679
+ const happyCliVersion = "1.1.10-aplus.317";
40680
+ const happyCliTag = "happy-cli-v1.1.10-aplus.317";
40681
+ const vendorCommit = "d5fcae31b2fd14942813f1937a2e141c39b6d412";
40610
40682
  const saycodeCliVersion = "0.8.2";
40611
- const happyServerVersion = "0.1.1";
40683
+ const happyServerVersion = "0.1.2";
40612
40684
  const releaseFeatures = { "mcpRuntimeRecovery": { "enabled": true, "releaseState": "released", "sourceBranch": "main", "sourceHead": "a79a10e288cf7775cb15955f716693c6a7df1640", "requiredCommit": "975e32cf" } };
40613
40685
  const pin = {
40614
40686
  happyCliPackageName,
@@ -54198,8 +54270,8 @@ function isMachineTokensStoreValid(value2) {
54198
54270
  return normalizeMachineTokensStore(value2).tokens.length === candidate.tokens.length;
54199
54271
  }
54200
54272
  function attachStandaloneLocalMachineRegistry(machine, localMachineId, ownerId, resources) {
54201
- if (!localMachineId || machine.id !== localMachineId) return machine;
54202
54273
  const existing = machine.registry && typeof machine.registry === "object" && !Array.isArray(machine.registry) ? machine.registry : {};
54274
+ if (!localMachineId || machine.id !== localMachineId) return { ...machine, registry: { ...existing, ownerId, type: "personal" } };
54203
54275
  const existingWorkspaceRoot = typeof existing.workspaceRoot === "string" ? existing.workspaceRoot.trim() : process.env.HAPPY_WORKSPACE_ROOT?.trim() ?? "";
54204
54276
  return {
54205
54277
  ...machine,
@@ -54402,9 +54474,6 @@ const chatWorkEn = {
54402
54474
  "trialStarter.tips.title": "Connect to work with your email and documents in chat.",
54403
54475
  "trialStarter.upload.action": "Upload my file",
54404
54476
  "trialStarter.upload.hint": "Word, Excel or PDF as is",
54405
- "chatWork.replaceTitle": "Replace your draft?",
54406
- "chatWork.replaceBody": "Your files stay attached. Only the draft is replaced.",
54407
- "chatWork.replace": "Use example",
54408
54477
  "chatWork.cancel": "Cancel",
54409
54478
  "chatWork.preparing": "Preparing samples…",
54410
54479
  "chatWork.sampleFailed": "Could not prepare samples. Try again or add your files.",
@@ -55035,6 +55104,10 @@ const organizationStartEn = {
55035
55104
  "organizationStart.diagnostic.action.publicMissing": "Ask your organization administrator to check the shared credentials, then reconnect.",
55036
55105
  "organizationStart.diagnostic.reason.publicApply": "Company shared AI credentials could not be applied to this computer.",
55037
55106
  "organizationStart.diagnostic.action.publicApply": "Check the network and reconnect. If it keeps failing, send diagnostics to your administrator.",
55107
+ "organizationStart.diagnostic.reason.notDedicated": "This PC is not registered as this account's dedicated organization PC.",
55108
+ "organizationStart.diagnostic.action.notDedicated": "Ask your organization administrator to register this PC again as your dedicated PC under Organization admin → PCs.",
55109
+ "organizationStart.diagnostic.reason.registrationChanged": "This PC's organization registration was changed or deleted, so it cannot connect with this account.",
55110
+ "organizationStart.diagnostic.action.registrationChanged": "Ask your organization administrator to check this PC's registration under Organization admin → PCs, then try again.",
55038
55111
  "organizationStart.diagnostic.reason.publicVerify": "Shared credentials were applied, but usable AI authentication was not confirmed.",
55039
55112
  "organizationStart.diagnostic.action.publicVerify": "Ask your administrator to restore the latest shared credentials, then reconnect."
55040
55113
  };
@@ -55272,6 +55345,8 @@ const chatSchedulesEn = {
55272
55345
  "chatSchedules.navigation": "Schedules",
55273
55346
  "chatSchedules.new": "New task",
55274
55347
  "chatSchedules.edit": "Edit",
55348
+ "chatSchedules.partialRead": "Some tasks could not be read. Please try again.",
55349
+ "chatSchedules.resumeDraft": "Resume draft",
55275
55350
  "chatSchedules.retry": "Try again",
55276
55351
  "chatSchedules.loading": "Loading scheduled tasks…",
55277
55352
  "chatSchedules.loadError": "Could not load tasks. Try again.",
@@ -55652,7 +55727,7 @@ const machineUsageClaudeEn = {
55652
55727
  "machineUsage.coverageUnknown": "model limits unknown",
55653
55728
  "machineUsage.notObserved": "not observed yet",
55654
55729
  "machineUsage.scopeDiagnosis": "usage scope diagnosis required",
55655
- "machineUsage.sourceOrganizationCollector": "Organization collector",
55730
+ "machineUsage.organizationAccount": "Organization account",
55656
55731
  "machineUsage.probeTitle": "Personal usage observations",
55657
55732
  "machineUsage.probeCentral": "Organization usage is provided by the central collector. Local consent and refresh are unavailable.",
55658
55733
  "machineUsage.probeUpdateRequired": "Update the machine runtime or resolve this account reference to enable personal observations.",
@@ -56647,6 +56722,7 @@ const personalChatsEn = {
56647
56722
  "personalChats.automationSaved": "Automation settings saved",
56648
56723
  "personalChats.automationDeleted": "Automation deleted",
56649
56724
  "personalChats.title": "Personal Chats",
56725
+ "personalChats.compose": "Compose a new chat",
56650
56726
  "personalChats.newChat": "New chat",
56651
56727
  "personalChats.searchPlaceholder": "Search chats",
56652
56728
  "personalChats.sortRecent": "Sort by recent activity",
@@ -56952,7 +57028,33 @@ const collaborationMachineEn = {
56952
57028
  "collaboration.pcOffline": "The project PC is offline. Existing conversations with read access remain available; new runs need the PC to reconnect.",
56953
57029
  "collaboration.pcUnavailable": "Project PC information could not be verified. Reading existing conversations and starting new work have separate permissions. Ask the owner to check PC access and connection.",
56954
57030
  "collaboration.dedicatedPcUnavailable": "Collaboration is unavailable on dedicated PCs.",
56955
- "collaboration.personalPcUnavailable": "Collaboration is unavailable on personal PCs."
57031
+ "collaboration.personalPcUnavailable": "Collaboration is unavailable on personal PCs.",
57032
+ "machineSharing.title": "PC sharing settings",
57033
+ "machineSharing.share": "Make shared",
57034
+ "machineSharing.dedicated": "Make dedicated",
57035
+ "machineSharing.save": "Save",
57036
+ "machineSharing.saving": "Saving…",
57037
+ "machineSharing.accessHeading": "Users with PC access",
57038
+ "machineSharing.shareHelp": "Sharing starts with access for you only.",
57039
+ "machineSharing.selectedHelp": "Allowed users can run work on this PC.",
57040
+ "machineSharing.confirmInvite": "Grant PC access and invite?",
57041
+ "machineSharing.confirmInviteHelp": "Selected users will be able to use this PC. They join the project after accepting the invitation.",
57042
+ "machineSharing.grantAndInvite": "Grant access and invite",
57043
+ "machineSharing.accessGranted": "PC access was granted. Retry any failed project invitations.",
57044
+ "machineSharing.stateChanged": "PC settings changed. Check again.",
57045
+ "machineSharing.aiAuthRequired": "This PC’s AI credentials cannot be converted to shared use.",
57046
+ "machineSharing.projectConflict": "Existing collaborators would lose access.",
57047
+ "machineSharing.membersUnavailable": "Could not verify project members. Try again shortly.",
57048
+ "machineSharing.runtimeUnavailable": "Check the PC connection and try again.",
57049
+ "machineSharing.ownerRequired": "Ask the PC owner or machine administrator to grant access.",
57050
+ "machineSharing.serverUnavailable": "Sharing settings are unavailable. Check the server update.",
57051
+ "machineSharing.requestFailed": "Could not confirm the sharing result. Check again.",
57052
+ "machineSharing.loadFailed": "Could not load sharing settings.",
57053
+ "machineSharing.retry": "Check again",
57054
+ "machineSharing.cancel": "Cancel",
57055
+ "machineSharing.close": "Close",
57056
+ "machineSharing.allMembers": "All organization members",
57057
+ "machineSharing.convertFirst": "Make this PC shared to collaborate."
56956
57058
  };
56957
57059
  const collaborationEn = {
56958
57060
  ...collaborationMachineEn,
@@ -57251,6 +57353,8 @@ const newSessionProfileEn = {
57251
57353
  "newSession.profile.none": "No profile",
57252
57354
  "newSession.profile.executionSettings": "Execution settings",
57253
57355
  "newSession.profile.editSettings": "Edit",
57356
+ "newSession.profile.saving": "Saving…",
57357
+ "newSession.profile.temporarySelection": "Shown for the current environment. Your saved selection stays unchanged until you choose an AI, model, or effort.",
57254
57358
  "newSession.profile.saveChanges": "Save changes",
57255
57359
  "newSession.profile.instructionsField": "Extra instructions",
57256
57360
  "newSession.profile.badgeIconField": "Badge icon",
@@ -58023,14 +58127,12 @@ const agentBrowserConsoleEn = {
58023
58127
  "browserPanel.agentBrowserUnauthorized": "Your sign-in has expired. Sign in again, then open the console.",
58024
58128
  "browserPanel.agentBrowserExpired": "Console access has expired. Open the AI Browser task console again.",
58025
58129
  "browserPanel.agentBrowserFailed": "Could not get access to the AI Browser console. Try again shortly.",
58026
- "agentBrowser.chat.showNotice": "Show AI Browser notice",
58027
- "agentBrowser.chat.showNoticeHint": "Show the browser console notice at the top of conversations.",
58028
- "agentBrowser.chat.title": "AI Browser",
58130
+ "agentBrowser.chat.showNotice": "Show AI Browser button",
58131
+ "agentBrowser.chat.showNoticeHint": "Show the Open AI Browser button at the top right of conversations.",
58029
58132
  "agentBrowser.chat.notice": "When a login or approval is needed, you can handle it yourself in the AI Browser console.",
58030
58133
  "agentBrowser.chat.ownersBrowser": "Browser tasks in this chat run with the logins of the person who started it.",
58031
58134
  "agentBrowser.chat.ownersBrowserNamed": "Browser tasks in this chat run with {name}'s logins.",
58032
- "agentBrowser.chat.open": "Open browser console",
58033
- "agentBrowser.chat.dismiss": "Dismiss AI Browser notice",
58135
+ "agentBrowser.chat.open": "Open AI Browser",
58034
58136
  "agentBrowser.chat.modeMismatch": "This machine's AI Browser was installed for a different mode (shared/dedicated) than its machine type, so the browser is unavailable. Ask an administrator to check the machine's settings.",
58035
58137
  "agentBrowser.confirm.title": "This runs with someone else's logins",
58036
58138
  "agentBrowser.confirm.titleNamed": "This runs with {name}'s logins",
@@ -58349,7 +58451,7 @@ const designGuideComponentEn = {
58349
58451
  "designGuide.components.tabs.rule2": "The selected tab and hover use the accent surface. Do not use a blue underline.",
58350
58452
  "designGuide.components.tabs.rule3": "Every tab has a close button (24px). When there are many tabs, the row scrolls sideways instead of wrapping.",
58351
58453
  "designGuide.components.tabs.rule4": "The new tab button is a 28px icon button at the end of the row: a compose icon (SquarePen) in the center conversation row and a more menu icon (…) in the right tool row. Arrow keys move between tabs.",
58352
- "designGuide.components.tabs.rule5": "Only the home screen mode tabs are 36px pills. The tabs are Chat and Develop, and a Build tab appears between them only when the organization is buzzni. In these tabs and the sidebar Chat/Project tabs, the selection mark slides over 260ms.",
58454
+ "designGuide.components.tabs.rule5": "Project shows 36px pill tabs for Build and Develop to all users. Their selection mark slides over 260ms. Chat opens its own composer from the sidebar menu.",
58353
58455
  "designGuide.components.tabs.rule6": "Center chat tabs and right tool tabs can be dragged to reorder. Cmd+W closes the tab last clicked or focused the same way as its close button, and never closes the window, even on the last tab. The close button tooltip names this shortcut.",
58354
58456
  "designGuide.components.tabs.note": "The work tab bar is drawn inside WorkspaceHost together with the workspace state, so it cannot render on its own. This shows the look with the same classes; once phase 2 splits the tab bar into a component, the real one replaces it. Today tabs use a 7px radius and close buttons 5px, which are off the radius steps. The right tool tabs (.workspace-tool-tab) share the values but have their own classes; phase 2 merges them into one component.",
58355
58457
  "designGuide.components.listRows": "List rows",
@@ -58358,7 +58460,7 @@ const designGuideComponentEn = {
58358
58460
  "designGuide.components.listRows.rule2": "A row ends with only a more menu (…) and a pin button; rename, archive, copy, and delete live in the more menu. Both buttons appear only on hover or keyboard focus, and take no title space while hidden. Conversation lists (Project and Chat) have no leading conversation icon, and the Chat list always shows the pin on pinned rows.",
58359
58461
  "designGuide.components.listRows.rule3": "Row titles are cut to one line, and the full name shows in the hover tooltip.",
58360
58462
  "designGuide.components.listRows.rule4": "While dragging to reorder, draw a 2px brand-color line where the row will land, matching the actual drop position.",
58361
- "designGuide.components.listRows.rule5": "The primary items at the top of the sidebar (Saycode home, work board, integrations) use 44px rows, 15px text, and 18px icons, and the current destination gets a background lightly mixed with the brand color.",
58463
+ "designGuide.components.listRows.rule5": "The primary sidebar menus (Chat, Project, work board, scheduled tasks, integrations) use 44px rows, 15px text, and 18px icons. Work board and scheduled tasks follow their display settings. Hover and selection use a subtle brand-color background. In Chat and Project details, only the current list item is selected; the top menus remain unselected.",
58362
58464
  "designGuide.components.toasts": "Global notices",
58363
58465
  "designGuide.components.toasts.intro": "Notices shown at the top center of the window, whichever screen they come from. The buttons show real notices.",
58364
58466
  "designGuide.components.toasts.rule1": "Use the shared FloatingNotice and this live example for every toast. Show it at the top center and hide it with empty text so its exit can finish.",
@@ -58887,6 +58989,9 @@ const machineSetupEn = {
58887
58989
  "machineSetup.installTitle": "Install the CLI",
58888
58990
  "machineSetup.cloudTitle": "Saycode Cloud",
58889
58991
  "machineSetup.standaloneTitle": "Standalone server",
58992
+ "machineSetup.selfHostTitle": "Connect a machine to this server",
58993
+ "machineSetup.pairingCode": "connection code",
58994
+ "machineSetup.selfHostHelp": "The sign-in command on the new machine shows a connection code. Approve that code on the server, then start the daemon on the new machine.",
58890
58995
  "machineSetup.serverAddress": "server URL",
58891
58996
  "machineSetup.authHelp": "Run happy auth login to register the machine through the mobile app or the displayed web URL.",
58892
58997
  "machineSetup.organizationHelp": "Register dedicated or shared organization machines by running the command issued below on the new machine."
@@ -59032,9 +59137,7 @@ const en = {
59032
59137
  "networkDataSaver.deferred.memory": "Memory Layer conversation backfill",
59033
59138
  "networkDataSaver.deferred.gitPr": "Background Git and PR refreshes",
59034
59139
  "happyCliUpdate.title": "Aplus CLI update",
59035
- "happyCliUpdate.checkTitle": "Aplus CLI update",
59036
59140
  "happyCliUpdate.managerTitle": "Aplus CLI update",
59037
- "happyCliUpdate.impact": "Machine connections may pause during the update.",
59038
59141
  "happyCliUpdate.update": "Update",
59039
59142
  "happyCliUpdate.updating": "Updating…",
59040
59143
  "happyCliUpdate.updated": "Updated",
@@ -61674,9 +61777,6 @@ const chatWorkZh = {
61674
61777
  "trialStarter.tips.title": "连接后,即可在聊天中处理自己的邮件和文档。",
61675
61778
  "trialStarter.upload.action": "添加自己的文件",
61676
61779
  "trialStarter.upload.hint": "Word、Excel、PDF 均可",
61677
- "chatWork.replaceTitle": "替换为示例?",
61678
- "chatWork.replaceBody": "只替换输入内容,您的文件会保留。",
61679
- "chatWork.replace": "使用示例",
61680
61780
  "chatWork.cancel": "取消",
61681
61781
  "chatWork.preparing": "正在准备示例…",
61682
61782
  "chatWork.sampleFailed": "无法准备示例。请重试或添加自己的文件。",
@@ -62307,6 +62407,10 @@ const organizationStartZh = {
62307
62407
  "organizationStart.diagnostic.action.publicMissing": "请组织管理员确认共享认证已注册,然后重新连接。",
62308
62408
  "organizationStart.diagnostic.reason.publicApply": "无法将公司的共享 AI 认证应用到此电脑。",
62309
62409
  "organizationStart.diagnostic.action.publicApply": "请检查网络后重新连接。如果持续失败,请将诊断信息发送给组织管理员。",
62410
+ "organizationStart.diagnostic.reason.notDedicated": "此电脑未登记为该账号的组织专用电脑。",
62411
+ "organizationStart.diagnostic.action.notDedicated": "请联系组织管理员,在 组织管理 → 电脑 中将此电脑重新登记为你的专用电脑。",
62412
+ "organizationStart.diagnostic.reason.registrationChanged": "此电脑的组织登记已被更改或删除,无法用此账号连接。",
62413
+ "organizationStart.diagnostic.action.registrationChanged": "请联系组织管理员在 组织管理 → 电脑 中检查此电脑的登记,然后重试。",
62310
62414
  "organizationStart.diagnostic.reason.publicVerify": "共享认证已应用,但未能确认 AI 认证可用。",
62311
62415
  "organizationStart.diagnostic.action.publicVerify": "请组织管理员恢复最新共享认证,然后重新连接。"
62312
62416
  };
@@ -62544,6 +62648,8 @@ const chatSchedulesZh = {
62544
62648
  "chatSchedules.navigation": "计划",
62545
62649
  "chatSchedules.new": "新建任务",
62546
62650
  "chatSchedules.edit": "编辑",
62651
+ "chatSchedules.partialRead": "部分预约无法读取。请重试。",
62652
+ "chatSchedules.resumeDraft": "继续填写",
62547
62653
  "chatSchedules.retry": "重试",
62548
62654
  "chatSchedules.loading": "正在加载计划任务…",
62549
62655
  "chatSchedules.loadError": "无法加载任务,请重试。",
@@ -62924,7 +63030,7 @@ const machineUsageClaudeZh = {
62924
63030
  "machineUsage.coverageUnknown": "模型额度未知",
62925
63031
  "machineUsage.notObserved": "尚未观测",
62926
63032
  "machineUsage.scopeDiagnosis": "需要诊断用量权限",
62927
- "machineUsage.sourceOrganizationCollector": "组织采集器",
63033
+ "machineUsage.organizationAccount": "组织账号",
62928
63034
  "machineUsage.probeTitle": "个人用量观测",
62929
63035
  "machineUsage.probeCentral": "组织用量由中央收集器提供。不提供本地同意和刷新操作。",
62930
63036
  "machineUsage.probeUpdateRequired": "启用个人观测需要更新机器运行时或确认账户引用。",
@@ -63919,6 +64025,7 @@ const personalChatsZh = {
63919
64025
  "personalChats.automationSaved": "自动化设置已保存",
63920
64026
  "personalChats.automationDeleted": "自动化已删除",
63921
64027
  "personalChats.title": "我的对话",
64028
+ "personalChats.compose": "撰写新对话",
63922
64029
  "personalChats.newChat": "新对话",
63923
64030
  "personalChats.searchPlaceholder": "搜索对话",
63924
64031
  "personalChats.sortRecent": "按最近活动排序",
@@ -64224,7 +64331,33 @@ const collaborationMachineZh = {
64224
64331
  "collaboration.pcOffline": "工作电脑已离线。拥有读取权限的现有对话仍可查看;新的运行需要电脑连接。",
64225
64332
  "collaboration.pcUnavailable": "无法确认工作电脑信息。阅读现有对话和启动新任务的权限不同。请联系所有者检查电脑访问设置与连接。",
64226
64333
  "collaboration.dedicatedPcUnavailable": "专用电脑不支持协作。",
64227
- "collaboration.personalPcUnavailable": "个人电脑不支持协作。"
64334
+ "collaboration.personalPcUnavailable": "个人电脑不支持协作。",
64335
+ "machineSharing.title": "PC 共享设置",
64336
+ "machineSharing.share": "改为共享",
64337
+ "machineSharing.dedicated": "改为专用",
64338
+ "machineSharing.save": "保存",
64339
+ "machineSharing.saving": "正在保存…",
64340
+ "machineSharing.accessHeading": "可使用 PC 的用户",
64341
+ "machineSharing.shareHelp": "改为共享后,最初只有你可以使用。",
64342
+ "machineSharing.selectedHelp": "获准用户可以在此 PC 上运行任务。",
64343
+ "machineSharing.confirmInvite": "添加 PC 访问权限并邀请?",
64344
+ "machineSharing.confirmInviteHelp": "所选用户将能使用此 PC。接受邀请后才会加入项目。",
64345
+ "machineSharing.grantAndInvite": "添加权限并邀请",
64346
+ "machineSharing.accessGranted": "已添加 PC 访问权限。请重试失败的项目邀请。",
64347
+ "machineSharing.stateChanged": "PC 设置已更改,请重新确认。",
64348
+ "machineSharing.aiAuthRequired": "此 PC 的 AI 凭据无法转换为共享使用。",
64349
+ "machineSharing.projectConflict": "现有协作者会失去访问权限,无法减少权限。",
64350
+ "machineSharing.membersUnavailable": "无法确认项目成员,请稍后重试。",
64351
+ "machineSharing.runtimeUnavailable": "请确认 PC 连接后重试。",
64352
+ "machineSharing.ownerRequired": "请联系 PC 所有者或机器管理员添加访问权限。",
64353
+ "machineSharing.serverUnavailable": "共享设置不可用,请检查服务器更新。",
64354
+ "machineSharing.requestFailed": "无法确认共享设置结果,请重新确认。",
64355
+ "machineSharing.loadFailed": "无法加载共享设置。",
64356
+ "machineSharing.retry": "重新确认",
64357
+ "machineSharing.cancel": "取消",
64358
+ "machineSharing.close": "关闭",
64359
+ "machineSharing.allMembers": "全部组织成员",
64360
+ "machineSharing.convertFirst": "改为共享 PC 后即可协作。"
64228
64361
  };
64229
64362
  const collaborationZh = {
64230
64363
  ...collaborationMachineZh,
@@ -64523,6 +64656,8 @@ const newSessionProfileZh = {
64523
64656
  "newSession.profile.none": "无配置",
64524
64657
  "newSession.profile.executionSettings": "执行设置",
64525
64658
  "newSession.profile.editSettings": "编辑",
64659
+ "newSession.profile.saving": "正在保存…",
64660
+ "newSession.profile.temporarySelection": "按当前环境显示。在您手动更改 AI、模型或推理强度之前,已保存的选择将保持不变。",
64526
64661
  "newSession.profile.saveChanges": "保存更改",
64527
64662
  "newSession.profile.instructionsField": "附加指令",
64528
64663
  "newSession.profile.badgeIconField": "标记图标",
@@ -65295,14 +65430,12 @@ const agentBrowserConsoleZh = {
65295
65430
  "browserPanel.agentBrowserUnauthorized": "登录已过期。请重新登录后再打开控制台。",
65296
65431
  "browserPanel.agentBrowserExpired": "控制台访问权限已过期。请重新打开AI 浏览器任务控制台。",
65297
65432
  "browserPanel.agentBrowserFailed": "无法获取AI 浏览器控制台权限。请稍后重试。",
65298
- "agentBrowser.chat.showNotice": "显示 AI 浏览器提示",
65299
- "agentBrowser.chat.showNoticeHint": "在对话顶部显示打开浏览器控制台的提示。",
65300
- "agentBrowser.chat.title": "AI 浏览器",
65433
+ "agentBrowser.chat.showNotice": "显示 AI 浏览器按钮",
65434
+ "agentBrowser.chat.showNoticeHint": "在对话右上角显示打开 AI 浏览器按钮。",
65301
65435
  "agentBrowser.chat.notice": "需要登录或审批时,可以在AI 浏览器控制台中亲自处理。",
65302
65436
  "agentBrowser.chat.ownersBrowser": "此对话的浏览器任务使用对话创建者的登录状态执行。",
65303
65437
  "agentBrowser.chat.ownersBrowserNamed": "此对话的浏览器任务使用 {name} 的登录状态执行。",
65304
- "agentBrowser.chat.open": "打开浏览器控制台",
65305
- "agentBrowser.chat.dismiss": "关闭AI 浏览器提示",
65438
+ "agentBrowser.chat.open": "打开 AI 浏览器",
65306
65439
  "agentBrowser.chat.modeMismatch": "此机器的AI 浏览器安装模式(共享/专用)与机器类型不一致,无法使用浏览器。请联系管理员检查机器设置。",
65307
65440
  "agentBrowser.confirm.title": "将使用他人的登录状态执行",
65308
65441
  "agentBrowser.confirm.titleNamed": "将使用 {name} 的登录状态执行",
@@ -65621,7 +65754,7 @@ const designGuideComponentZh = {
65621
65754
  "designGuide.components.tabs.rule2": "选中的标签和悬停使用 accent 面区分。不使用蓝色下划线。",
65622
65755
  "designGuide.components.tabs.rule3": "每个标签都有关闭按钮(24px)。标签较多时不换行,而是横向滚动。",
65623
65756
  "designGuide.components.tabs.rule4": "新建标签按钮用 28px 图标按钮放在标签行末尾。中间对话标签行使用新建对话图标(SquarePen),右侧工具标签行使用更多菜单图标(…)。可以用方向键在标签之间移动。",
65624
- "designGuide.components.tabs.rule5": "只有首页的模式标签是 36px 的胶囊形。标签为 Chat 和 Develop,只有当组织为 buzzni 时,Build 标签才会出现在两者之间。这些标签和侧边栏的 Chat/Project 标签的选中标记会在 260ms 内移动。",
65757
+ "designGuide.components.tabs.rule5": "Project 为所有用户显示 Build 和 Develop 的36px胶囊标签,选中标记在260ms内滑动。Chat 从侧边栏菜单打开独立的输入界面。",
65625
65758
  "designGuide.components.tabs.rule6": "中间的对话标签和右侧的工具标签可以拖动调整顺序。Cmd+W 会以与关闭按钮相同的方式关闭最后点击或聚焦的标签,即使是最后一个标签也不会关闭窗口。关闭按钮的提示中写明这个快捷键。",
65626
65759
  "designGuide.components.tabs.note": "工作标签行在 WorkspaceHost 中与工作状态一起绘制,无法单独渲染。这里用相同的类只展示外观,第二阶段把标签行拆成组件后再换成真实组件。目前标签圆角为 7px,关闭按钮为 5px,与圆角等级不一致。右侧工具标签(.workspace-tool-tab)数值相同,但使用单独的类,第二阶段将合并为一个组件。",
65627
65760
  "designGuide.components.listRows": "列表行",
@@ -65630,7 +65763,7 @@ const designGuideComponentZh = {
65630
65763
  "designGuide.components.listRows.rule2": "行末只放更多菜单(…)和置顶按钮。重命名、归档、复制和删除都在更多菜单中。两个按钮只在悬停或键盘聚焦时显示,隐藏时不占用标题空间。对话列表(Project 和 Chat)的行首不放对话图标,Chat 列表中已置顶的行始终显示置顶图标。",
65631
65764
  "designGuide.components.listRows.rule3": "行标题截断为一行,完整名称通过悬停提示显示。",
65632
65765
  "designGuide.components.listRows.rule4": "拖动调整顺序时,在将要放下的位置画一条 2px 的品牌色线,并与实际放下的位置一致。",
65633
- "designGuide.components.listRows.rule5": "侧边栏顶部的主要菜单(Saycode 首页、工作看板、外部集成)使用 44px 的行、15px 的文字和 18px 的图标,当前目的地用轻微混入品牌色的背景标示。",
65766
+ "designGuide.components.listRows.rule5": "侧边栏顶部的主要菜单(Chat、Project、工作看板、预约、外部集成)使用 44px 的行、15px 的文字和 18px 的图标。工作看板和预约按显示设置显示。悬停和选中状态使用淡品牌色背景;在 Chat 和 Project 详情中,仅选中当前列表项,顶部菜单保持未选中。",
65634
65767
  "designGuide.components.toasts": "全局通知",
65635
65768
  "designGuide.components.toasts.intro": "无论在哪个界面发生,都显示在窗口顶部中间的通知。点击按钮会显示真实的通知。",
65636
65769
  "designGuide.components.toasts.rule1": "所有 Toast 都使用公共 FloatingNotice 和此实际示例。显示在顶部中央,通过空 text 隐藏,让退出效果完成。",
@@ -66159,6 +66292,9 @@ const machineSetupZh = {
66159
66292
  "machineSetup.installTitle": "安装 CLI",
66160
66293
  "machineSetup.cloudTitle": "Saycode 云端",
66161
66294
  "machineSetup.standaloneTitle": "独立服务器",
66295
+ "machineSetup.selfHostTitle": "将电脑连接到此服务器",
66296
+ "machineSetup.pairingCode": "连接码",
66297
+ "machineSetup.selfHostHelp": "在新电脑上运行登录命令后会显示连接码。请在服务器上批准该连接码,然后在新电脑上启动守护进程。",
66162
66298
  "machineSetup.serverAddress": "服务器地址",
66163
66299
  "machineSetup.authHelp": "运行 happy auth login 后,可以通过移动应用或显示的网页 URL 注册机器。",
66164
66300
  "machineSetup.organizationHelp": "请在新机器上运行下方生成的命令,注册组织专用或共享机器。"
@@ -66304,9 +66440,7 @@ const zh = {
66304
66440
  "networkDataSaver.deferred.memory": "Memory Layer对话回填",
66305
66441
  "networkDataSaver.deferred.gitPr": "后台Git和PR刷新",
66306
66442
  "happyCliUpdate.title": "Aplus CLI 更新",
66307
- "happyCliUpdate.checkTitle": "Aplus CLI 更新",
66308
66443
  "happyCliUpdate.managerTitle": "Aplus CLI 更新",
66309
- "happyCliUpdate.impact": "更新期间机器连接可能会短暂中断。",
66310
66444
  "happyCliUpdate.update": "更新",
66311
66445
  "happyCliUpdate.updating": "正在更新…",
66312
66446
  "happyCliUpdate.updated": "已更新",
@@ -68946,9 +69080,6 @@ const chatWorkJa = {
68946
69080
  "trialStarter.tips.title": "連携すると、メールや文書をチャットで扱えます。",
68947
69081
  "trialStarter.upload.action": "ファイルをアップロード",
68948
69082
  "trialStarter.upload.hint": "Word・Excel・PDF はそのまま",
68949
- "chatWork.replaceTitle": "例に置き換えますか?",
68950
- "chatWork.replaceBody": "入力内容のみ置き換えます。自分のファイルは残ります。",
68951
- "chatWork.replace": "例を使う",
68952
69083
  "chatWork.cancel": "キャンセル",
68953
69084
  "chatWork.preparing": "サンプル準備中…",
68954
69085
  "chatWork.sampleFailed": "準備できませんでした。再試行するか自分のファイルを追加してください。",
@@ -69579,6 +69710,10 @@ const organizationStartJa = {
69579
69710
  "organizationStart.diagnostic.action.publicMissing": "組織管理者に共有認証の登録を確認してもらい、再接続してください。",
69580
69711
  "organizationStart.diagnostic.reason.publicApply": "会社の共有AI認証をこのコンピューターに適用できませんでした。",
69581
69712
  "organizationStart.diagnostic.action.publicApply": "ネットワークを確認して再接続してください。失敗が続く場合は診断情報を組織管理者に送ってください。",
69713
+ "organizationStart.diagnostic.reason.notDedicated": "このPCはこのアカウントの組織専用PCとして登録されていません。",
69714
+ "organizationStart.diagnostic.action.notDedicated": "組織管理者に、組織管理 → PC でこのPCをこのアカウントの専用PCとして再登録するよう依頼してください。",
69715
+ "organizationStart.diagnostic.reason.registrationChanged": "このPCの組織登録が変更または削除されたため、このアカウントで接続できません。",
69716
+ "organizationStart.diagnostic.action.registrationChanged": "組織管理者に、組織管理 → PC でこのPCの登録を確認するよう依頼してから、もう一度お試しください。",
69582
69717
  "organizationStart.diagnostic.reason.publicVerify": "共有認証を適用しましたが、AI認証の利用を確認できませんでした。",
69583
69718
  "organizationStart.diagnostic.action.publicVerify": "組織管理者に最新の共有認証の復旧を依頼してから再接続してください。"
69584
69719
  };
@@ -69816,6 +69951,8 @@ const chatSchedulesJa = {
69816
69951
  "chatSchedules.navigation": "予約",
69817
69952
  "chatSchedules.new": "新規予約",
69818
69953
  "chatSchedules.edit": "編集",
69954
+ "chatSchedules.partialRead": "一部の予約を確認できませんでした。もう一度確認してください。",
69955
+ "chatSchedules.resumeDraft": "入力を再開",
69819
69956
  "chatSchedules.retry": "再確認",
69820
69957
  "chatSchedules.loading": "予約タスクを読み込み中…",
69821
69958
  "chatSchedules.loadError": "予約を読み込めませんでした。再確認してください。",
@@ -70196,7 +70333,7 @@ const machineUsageClaudeJa = {
70196
70333
  "machineUsage.coverageUnknown": "モデル制限不明",
70197
70334
  "machineUsage.notObserved": "未観測",
70198
70335
  "machineUsage.scopeDiagnosis": "使用量権限の診断が必要",
70199
- "machineUsage.sourceOrganizationCollector": "組織コレクター",
70336
+ "machineUsage.organizationAccount": "組織アカウント",
70200
70337
  "machineUsage.probeTitle": "個人の使用量観測",
70201
70338
  "machineUsage.probeCentral": "組織の使用量は中央コレクターが提供します。ローカルの同意と更新は利用できません。",
70202
70339
  "machineUsage.probeUpdateRequired": "個人の観測にはマシンランタイムの更新またはアカウント参照の確認が必要です。",
@@ -71191,6 +71328,7 @@ const personalChatsJa = {
71191
71328
  "personalChats.automationSaved": "自動化の設定を保存しました",
71192
71329
  "personalChats.automationDeleted": "自動化を削除しました",
71193
71330
  "personalChats.title": "マイチャット",
71331
+ "personalChats.compose": "新しいチャットを作成",
71194
71332
  "personalChats.newChat": "新しいチャット",
71195
71333
  "personalChats.searchPlaceholder": "チャットを検索",
71196
71334
  "personalChats.sortRecent": "最近のアクティビティ順に並べ替え",
@@ -71496,7 +71634,33 @@ const collaborationMachineJa = {
71496
71634
  "collaboration.pcOffline": "作業PCはオフラインです。閲覧権限のある既存の会話は読めますが、新しい実行にはPCの接続が必要です。",
71497
71635
  "collaboration.pcUnavailable": "作業PC情報を確認できませんでした。会話の閲覧と新しい実行の権限は異なります。所有者にPCのアクセス設定と接続を確認してください。",
71498
71636
  "collaboration.dedicatedPcUnavailable": "専用PCでは共同作業できません。",
71499
- "collaboration.personalPcUnavailable": "個人PCでは共同作業できません。"
71637
+ "collaboration.personalPcUnavailable": "個人PCでは共同作業できません。",
71638
+ "machineSharing.title": "PCの共有設定",
71639
+ "machineSharing.share": "共用に変更",
71640
+ "machineSharing.dedicated": "専用に変更",
71641
+ "machineSharing.save": "保存",
71642
+ "machineSharing.saving": "保存中…",
71643
+ "machineSharing.accessHeading": "PCを利用できるユーザー",
71644
+ "machineSharing.shareHelp": "共用への変更直後は自分だけが利用できます。",
71645
+ "machineSharing.selectedHelp": "許可したユーザーはこのPCで作業を実行できます。",
71646
+ "machineSharing.confirmInvite": "PCのアクセス権を追加して招待しますか?",
71647
+ "machineSharing.confirmInviteHelp": "選択したユーザーはこのPCを利用できます。プロジェクトには招待承認後に参加します。",
71648
+ "machineSharing.grantAndInvite": "権限を追加して招待",
71649
+ "machineSharing.accessGranted": "PCのアクセス権を追加しました。失敗したプロジェクト招待を再試行してください。",
71650
+ "machineSharing.stateChanged": "PCの設定が変わりました。再確認してください。",
71651
+ "machineSharing.aiAuthRequired": "このPCのAI認証は共用に変更できません。",
71652
+ "machineSharing.projectConflict": "共同作業中のユーザーがいるためアクセス権を減らせません。",
71653
+ "machineSharing.membersUnavailable": "参加者を確認できませんでした。後でもう一度お試しください。",
71654
+ "machineSharing.runtimeUnavailable": "PCの接続を確認して再試行してください。",
71655
+ "machineSharing.ownerRequired": "PCの所有者またはマシン管理者にアクセス権の追加を依頼してください。",
71656
+ "machineSharing.serverUnavailable": "共有設定を利用できません。サーバーの更新を確認してください。",
71657
+ "machineSharing.requestFailed": "共有設定の結果を確認できませんでした。再確認してください。",
71658
+ "machineSharing.loadFailed": "共有設定を読み込めませんでした。",
71659
+ "machineSharing.retry": "再確認",
71660
+ "machineSharing.cancel": "キャンセル",
71661
+ "machineSharing.close": "閉じる",
71662
+ "machineSharing.allMembers": "組織の全メンバー",
71663
+ "machineSharing.convertFirst": "共用に変更すると共同作業できます。"
71500
71664
  };
71501
71665
  const collaborationJa = {
71502
71666
  ...collaborationMachineJa,
@@ -71795,6 +71959,8 @@ const newSessionProfileJa = {
71795
71959
  "newSession.profile.none": "プロファイルなし",
71796
71960
  "newSession.profile.executionSettings": "実行設定",
71797
71961
  "newSession.profile.editSettings": "編集",
71962
+ "newSession.profile.saving": "保存中…",
71963
+ "newSession.profile.temporarySelection": "現在の環境に合わせて表示しています。AI・モデル・推論強度を直接変更するまで、保存した選択は保持されます。",
71798
71964
  "newSession.profile.saveChanges": "変更を保存",
71799
71965
  "newSession.profile.instructionsField": "追加の指示",
71800
71966
  "newSession.profile.badgeIconField": "バッジアイコン",
@@ -72567,14 +72733,12 @@ const agentBrowserConsoleJa = {
72567
72733
  "browserPanel.agentBrowserUnauthorized": "ログインの有効期限が切れました。再度ログインしてからコンソールを開いてください。",
72568
72734
  "browserPanel.agentBrowserExpired": "コンソールへのアクセス権限が期限切れです。AIブラウザのタスクコンソールを開き直してください。",
72569
72735
  "browserPanel.agentBrowserFailed": "AIブラウザのコンソール権限を取得できませんでした。しばらくしてから再試行してください。",
72570
- "agentBrowser.chat.showNotice": "AIブラウザの案内を表示",
72571
- "agentBrowser.chat.showNoticeHint": "会話の上部にブラウザコンソールを開く案内を表示します。",
72572
- "agentBrowser.chat.title": "AIブラウザ",
72736
+ "agentBrowser.chat.showNotice": "AIブラウザのボタンを表示",
72737
+ "agentBrowser.chat.showNoticeHint": "会話の右上にAIブラウザを開くボタンを表示します。",
72573
72738
  "agentBrowser.chat.notice": "ログインや承認が必要なときは、AIブラウザのコンソールで直接対応できます。",
72574
72739
  "agentBrowser.chat.ownersBrowser": "この会話のブラウザ作業は、会話を作成した人のログインで実行されます。",
72575
72740
  "agentBrowser.chat.ownersBrowserNamed": "この会話のブラウザ作業は {name} さんのログインで実行されます。",
72576
- "agentBrowser.chat.open": "ブラウザコンソールを開く",
72577
- "agentBrowser.chat.dismiss": "AIブラウザの案内を閉じる",
72741
+ "agentBrowser.chat.open": "AIブラウザを開く",
72578
72742
  "agentBrowser.chat.modeMismatch": "このマシンのAIブラウザのインストールモード(共有/専用)がマシン種別と異なるため、ブラウザを使えません。管理者にマシン設定の確認を依頼してください。",
72579
72743
  "agentBrowser.confirm.title": "他の人のログインで実行されます",
72580
72744
  "agentBrowser.confirm.titleNamed": "{name} さんのログインで実行されます",
@@ -72893,7 +73057,7 @@ const designGuideComponentJa = {
72893
73057
  "designGuide.components.tabs.rule2": "選択中のタブとホバーは accent の面で区別します。青い下線は使いません。",
72894
73058
  "designGuide.components.tabs.rule3": "すべてのタブに閉じるボタン(24px)を置きます。タブが多いときは折り返さず横にスクロールします。",
72895
73059
  "designGuide.components.tabs.rule4": "新しいタブのボタンはタブ行の最後に28pxのアイコンボタンで置きます。中央の会話タブ行は新しい会話の作成アイコン(SquarePen)、右側のツールタブ行はその他のメニューのアイコン(…)を使います。矢印キーでタブ間を移動できます。",
72896
- "designGuide.components.tabs.rule5": "ホーム画面のモードタブだけが36pxの錠剤形です。タブは Chat と Develop で、Build タブは組織が buzzni のときだけその間に表示されます。このタブとサイドバーの Chat/Project タブは、選択の印が260msで移ります。",
73060
+ "designGuide.components.tabs.rule5": "Project ではすべてのユーザーに Build・Develop の36pxピル型タブを表示し、選択表示は260msで移動します。Chat はサイドバーメニューから専用の入力画面を開きます。",
72897
73061
  "designGuide.components.tabs.rule6": "中央の会話タブと右側のツールタブはドラッグで順序を変えられます。Cmd+W は最後にクリックまたはフォーカスしたタブを閉じるボタンと同じ方法で閉じ、最後のタブでもウィンドウは閉じません。閉じるボタンのツールチップにこのショートカットを書きます。",
72898
73062
  "designGuide.components.tabs.note": "作業タブの行は WorkspaceHost の中で作業の状態と一緒に描かれるため、単独で描画できません。同じクラスで見た目だけを示し、ステップ2でタブ行を部品に分けたら実物に置き換えます。現在のタブの角の丸みは7px、閉じるボタンは5pxで、角の丸みの段階と異なります。右のツールタブ(.workspace-tool-tab)は値は同じですがクラスが別のため、ステップ2で1つの部品にまとめます。",
72899
73063
  "designGuide.components.listRows": "リストの行",
@@ -72902,7 +73066,7 @@ const designGuideComponentJa = {
72902
73066
  "designGuide.components.listRows.rule2": "行の端にはその他のメニュー(…)と固定ボタンだけを置きます。名前の変更、アーカイブ、コピー、削除はその他のメニューの中にあります。2つのボタンはホバーかキーボードフォーカスのときだけ表示し、隠れている間はタイトルの場所を取りません。会話一覧(Project、Chat)は行頭の会話アイコンを置かず、Chat 一覧では固定した行のピンを常に表示します。",
72903
73067
  "designGuide.components.listRows.rule3": "行のタイトルは1行に収め、全体の名前はホバーのツールチップで示します。",
72904
73068
  "designGuide.components.listRows.rule4": "ドラッグで並べ替えるときは、置かれる位置に2pxのブランド色の線を描き、実際に置かれる位置と一致させます。",
72905
- "designGuide.components.listRows.rule5": "サイドバー最上部の主要メニュー(Saycode ホーム、作業ボード、外部連携)は44pxの行、15pxの文字、18pxのアイコンで、現在の行き先はブランド色を薄く混ぜた背景で示します。",
73069
+ "designGuide.components.listRows.rule5": "サイドバー上部の主要メニュー(Chat、Project、作業ボード、予約、外部連携)は44pxの行、15pxの文字、18pxのアイコンを使用します。作業ボードと予約は表示設定に従います。ホバーと選択は淡いブランド色の背景で示し、Chat・Projectの詳細では上部メニューではなく現在のリスト項目だけを選択表示します。",
72906
73070
  "designGuide.components.toasts": "全体の通知",
72907
73071
  "designGuide.components.toasts.intro": "どの画面で起きたことでも、ウィンドウ上部の中央に出す通知です。ボタンを押すと実際の通知が出ます。",
72908
73072
  "designGuide.components.toasts.rule1": "すべてのトーストに共通の FloatingNotice とこの実例を使います。上部中央に表示し、空の text で非表示にして退場効果を完了させます。",
@@ -73431,6 +73595,9 @@ const machineSetupJa = {
73431
73595
  "machineSetup.installTitle": "CLIをインストール",
73432
73596
  "machineSetup.cloudTitle": "Saycodeクラウド",
73433
73597
  "machineSetup.standaloneTitle": "スタンドアロンサーバー",
73598
+ "machineSetup.selfHostTitle": "このサーバーにマシンを接続",
73599
+ "machineSetup.pairingCode": "接続コード",
73600
+ "machineSetup.selfHostHelp": "新しいマシンでログインコマンドを実行すると接続コードが表示されます。サーバーでそのコードを承認してから、新しいマシンでデーモンを起動してください。",
73434
73601
  "machineSetup.serverAddress": "サーバーURL",
73435
73602
  "machineSetup.authHelp": "happy auth loginを実行すると、モバイルアプリまたは表示されたWeb URLからマシンを登録できます。",
73436
73603
  "machineSetup.organizationHelp": "組織の専用・共有マシンは、以下で発行するコマンドを新しいマシンで実行して登録してください。"
@@ -73576,9 +73743,7 @@ const ja = {
73576
73743
  "networkDataSaver.deferred.memory": "Memory Layerの会話バックフィル",
73577
73744
  "networkDataSaver.deferred.gitPr": "バックグラウンドのGit・PR更新",
73578
73745
  "happyCliUpdate.title": "Aplus CLI 更新",
73579
- "happyCliUpdate.checkTitle": "Aplus CLI 更新",
73580
73746
  "happyCliUpdate.managerTitle": "Aplus CLI 更新",
73581
- "happyCliUpdate.impact": "更新中はマシン接続が一時的に切れる場合があります。",
73582
73747
  "happyCliUpdate.update": "更新",
73583
73748
  "happyCliUpdate.updating": "更新中…",
73584
73749
  "happyCliUpdate.updated": "更新済み",
@@ -76820,6 +76985,7 @@ async function installSystemdUnit(path2, unit, systemctl = exec) {
76820
76985
  const failure = error;
76821
76986
  throw new Error(describeUserManagerFailure({ code: failure.code, detail: failure.detail ?? failure.message ?? String(error) }));
76822
76987
  });
76988
+ await mkdir(dirname(path2), { recursive: true });
76823
76989
  const previous = existsSync(path2) ? await readFile(path2, "utf8") : null;
76824
76990
  const wasEnabled = previous !== null && await user("is-enabled", SYSTEMD_UNIT_NAME).then((out) => out.trim() === "enabled", () => false);
76825
76991
  const wasActive = previous !== null && await user("is-active", SYSTEMD_UNIT_NAME).then((out) => out.trim() === "active", () => false);
@@ -76847,12 +77013,12 @@ function serviceDefinitionPath(platform2) {
76847
77013
  async function installService(platform2, definition) {
76848
77014
  await mkdir(dirname(definition.logFile), { recursive: true, mode: 448 });
76849
77015
  const path2 = serviceDefinitionPath(platform2);
76850
- await mkdir(dirname(path2), { recursive: true });
76851
77016
  if (platform2 === "linux") {
76852
77017
  await installSystemdUnit(path2, systemdUserUnit(definition));
76853
77018
  const linger = await exec("loginctl", ["show-user", userInfo().username, "--property=Linger", "--value"]).catch(() => "");
76854
77019
  return { path: path2, lingerEnabled: linger.trim() === "" ? null : linger.trim() === "yes" };
76855
77020
  }
77021
+ await mkdir(dirname(path2), { recursive: true });
76856
77022
  await writeFile(path2, launchAgentPlist(definition));
76857
77023
  await exec("launchctl", ["bootout", `${launchDomain()}/${LAUNCH_AGENT_LABEL}`]).catch(() => "");
76858
77024
  await exec("launchctl", ["bootstrap", launchDomain(), path2]);
@@ -81855,7 +82021,7 @@ async function runServer(args, print) {
81855
82021
  throw error;
81856
82022
  }
81857
82023
  await Promise.all([layout.logsDir, layout.shimStoreDir, layout.happyHomeDir].map((dir) => mkdir(dir, { recursive: true, mode: 448 })));
81858
- configureProcessLedger({ userDataDir: join(layout.root, "ledger") });
82024
+ configureProcessLedger({ userDataDir: join(layout.root, "ledger"), log: serverLogWriter(layout, "process-ledger") });
81859
82025
  const server2 = new StandaloneServerManager(runtime.serverPackageDir, {
81860
82026
  dataDir: layout.dataDir,
81861
82027
  pgliteDir: layout.pgliteDir,
@@ -83933,7 +84099,7 @@ function parseContributions(value2, apiVersion, channelApiVersion) {
83933
84099
  if (parsed2.channels !== void 0) {
83934
84100
  result2.channels = parseExtensionChannelContributions(parsed2.channels);
83935
84101
  }
83936
- const ids = [
84102
+ const ids2 = [
83937
84103
  ...result2.commands ?? [],
83938
84104
  ...result2.settings ?? [],
83939
84105
  ...result2.panels ?? [],
@@ -83942,7 +84108,7 @@ function parseContributions(value2, apiVersion, channelApiVersion) {
83942
84108
  ...result2.artifactActions ?? [],
83943
84109
  ...result2.channels ?? []
83944
84110
  ].map((entry) => entry.id);
83945
- if (new Set(ids).size !== ids.length) fail$7("manifest.contributes", "duplicate contribution id");
84111
+ if (new Set(ids2).size !== ids2.length) fail$7("manifest.contributes", "duplicate contribution id");
83946
84112
  return result2;
83947
84113
  }
83948
84114
  function parseExtensionManifest(value2, options) {
@@ -84919,7 +85085,7 @@ function allowedEnvelope(value2) {
84919
85085
  if (Object.keys(event).some((key) => !permitted.has(key))) return null;
84920
85086
  if (!id(event.permissionId) || !id(event.turnId) || !id(event.channelRequestId) || !id(event.runtimeId)) return null;
84921
85087
  if (typeof event.createdAt !== "number" || !Number.isInteger(event.createdAt) || event.createdAt < 0) return null;
84922
- const ids = {
85088
+ const ids2 = {
84923
85089
  permissionId: event.permissionId,
84924
85090
  turnId: event.turnId,
84925
85091
  channelRequestId: event.channelRequestId,
@@ -84928,12 +85094,12 @@ function allowedEnvelope(value2) {
84928
85094
  };
84929
85095
  if (event.t === "channel-permission") {
84930
85096
  if (event.kind !== "generic" && event.kind !== "desktop-only") return null;
84931
- ev = { t: "channel-permission", ...ids, kind: event.kind };
85097
+ ev = { t: "channel-permission", ...ids2, kind: event.kind };
84932
85098
  } else {
84933
85099
  if (event.reason !== "answered" && event.reason !== "aborted" && event.reason !== "reset") {
84934
85100
  return null;
84935
85101
  }
84936
- ev = { t: "channel-permission-withdrawn", ...ids, reason: event.reason };
85102
+ ev = { t: "channel-permission-withdrawn", ...ids2, reason: event.reason };
84937
85103
  }
84938
85104
  } else if (event.t === "tool-call-end" && id(event.backgroundTaskId)) {
84939
85105
  ev = { t: "tool-call-end", call: "[background-task]", backgroundTaskId: event.backgroundTaskId };
@@ -94947,8 +95113,8 @@ async function loadSession(auth, sessionId) {
94947
95113
  }
94948
95114
  async function owningProjectId(auth, sessionId, allowedProjectIds) {
94949
95115
  for (const projectId of allowedProjectIds) {
94950
- const ids = await client(auth).getProjectSessionIds(projectId);
94951
- if (ids.includes(sessionId)) return projectId;
95116
+ const ids2 = await client(auth).getProjectSessionIds(projectId);
95117
+ if (ids2.includes(sessionId)) return projectId;
94952
95118
  }
94953
95119
  return null;
94954
95120
  }
@@ -95015,16 +95181,16 @@ function createChannelSessionOperations(deps = {}) {
95015
95181
  ),
95016
95182
  isOwnPersonalChat: (auth, sessionId) => isOwnPersonalChatSession(auth, sessionId),
95017
95183
  listSessions: async (auth, projectIds) => {
95018
- const ids = [];
95184
+ const ids2 = [];
95019
95185
  for (const projectId of projectIds) {
95020
95186
  const projectSessionIds = await client(auth).getProjectSessionIds(projectId).catch(() => []);
95021
- for (const id2 of projectSessionIds) if (!ids.includes(id2)) ids.push(id2);
95022
- if (ids.length >= MAX_CATALOG_SESSIONS) break;
95187
+ for (const id2 of projectSessionIds) if (!ids2.includes(id2)) ids2.push(id2);
95188
+ if (ids2.length >= MAX_CATALOG_SESSIONS) break;
95023
95189
  }
95024
- if (ids.length === 0) return [];
95190
+ if (ids2.length === 0) return [];
95025
95191
  return client(auth).lookupSessions(
95026
95192
  deriveCandidateKeys(auth),
95027
- ids.slice(0, MAX_CATALOG_SESSIONS),
95193
+ ids2.slice(0, MAX_CATALOG_SESSIONS),
95028
95194
  void 0,
95029
95195
  accountPrivateKeyBytes(auth)
95030
95196
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buzzni/saycode-cli",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "Drive Saycode sessions across your machines from the terminal.",
5
5
  "type": "module",
6
6
  "bin": {