tabby-agentdeck 1.1.3 → 1.2.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 (91) hide show
  1. package/CHANGELOG.md +150 -127
  2. package/LICENSE +21 -21
  3. package/README.ko.md +52 -590
  4. package/README.md +52 -562
  5. package/dist/accountBrowser.d.ts +4 -0
  6. package/dist/accountSession.d.ts +22 -0
  7. package/dist/accounts.d.ts +50 -0
  8. package/dist/agents.d.ts +15 -0
  9. package/dist/codexHooks.d.ts +23 -0
  10. package/dist/codexMeta.d.ts +87 -0
  11. package/dist/config.d.ts +110 -4
  12. package/dist/cursorVisibility.d.ts +33 -1
  13. package/dist/deck.service.d.ts +197 -20
  14. package/dist/devReload.service.d.ts +48 -0
  15. package/dist/devReload.stub.d.ts +19 -0
  16. package/dist/dock.d.ts +15 -0
  17. package/dist/i18n/af.d.ts +83 -0
  18. package/dist/i18n/bg.d.ts +83 -0
  19. package/dist/i18n/cs.d.ts +83 -0
  20. package/dist/i18n/da.d.ts +83 -0
  21. package/dist/i18n/de.d.ts +83 -0
  22. package/dist/i18n/en.d.ts +83 -0
  23. package/dist/i18n/es.d.ts +83 -0
  24. package/dist/i18n/fr.d.ts +83 -0
  25. package/dist/i18n/hr.d.ts +83 -0
  26. package/dist/i18n/id.d.ts +83 -0
  27. package/dist/i18n/it.d.ts +83 -0
  28. package/dist/i18n/ja.d.ts +83 -0
  29. package/dist/i18n/ko.d.ts +83 -0
  30. package/dist/i18n/pl.d.ts +83 -0
  31. package/dist/i18n/pt.d.ts +83 -0
  32. package/dist/i18n/ru.d.ts +83 -0
  33. package/dist/i18n/sidebar/af.d.ts +80 -0
  34. package/dist/i18n/sidebar/bg.d.ts +80 -0
  35. package/dist/i18n/sidebar/cs.d.ts +80 -0
  36. package/dist/i18n/sidebar/da.d.ts +80 -0
  37. package/dist/i18n/sidebar/de.d.ts +80 -0
  38. package/dist/i18n/sidebar/es.d.ts +80 -0
  39. package/dist/i18n/sidebar/fr.d.ts +80 -0
  40. package/dist/i18n/sidebar/hr.d.ts +80 -0
  41. package/dist/i18n/sidebar/id.d.ts +80 -0
  42. package/dist/i18n/sidebar/it.d.ts +80 -0
  43. package/dist/i18n/sidebar/ja.d.ts +80 -0
  44. package/dist/i18n/sidebar/pl.d.ts +80 -0
  45. package/dist/i18n/sidebar/pt.d.ts +80 -0
  46. package/dist/i18n/sidebar/ru.d.ts +80 -0
  47. package/dist/i18n/sidebar/sr.d.ts +80 -0
  48. package/dist/i18n/sidebar/sv.d.ts +80 -0
  49. package/dist/i18n/sidebar/tr.d.ts +80 -0
  50. package/dist/i18n/sidebar/uk.d.ts +80 -0
  51. package/dist/i18n/sidebar/zh-CN.d.ts +80 -0
  52. package/dist/i18n/sidebar/zh-TW.d.ts +80 -0
  53. package/dist/i18n/sr.d.ts +83 -0
  54. package/dist/i18n/sv.d.ts +83 -0
  55. package/dist/i18n/tr.d.ts +83 -0
  56. package/dist/i18n/uk.d.ts +83 -0
  57. package/dist/i18n/zh-CN.d.ts +83 -0
  58. package/dist/i18n/zh-TW.d.ts +83 -0
  59. package/dist/i18n.d.ts +3634 -0
  60. package/dist/index.d.ts +3 -1
  61. package/dist/index.js +109 -2
  62. package/dist/keybind.d.ts +121 -0
  63. package/dist/meta.d.ts +83 -0
  64. package/dist/nav.d.ts +29 -0
  65. package/dist/notify.service.d.ts +161 -1
  66. package/dist/project-root.d.ts +1 -1
  67. package/dist/reload.service.d.ts +57 -0
  68. package/dist/sessionLedger.d.ts +11 -6
  69. package/dist/sessionLedger.service.d.ts +3 -0
  70. package/dist/sessionMailbox.d.ts +31 -0
  71. package/dist/sessionSearch.d.ts +41 -0
  72. package/dist/sessionSearchPanel.d.ts +36 -0
  73. package/dist/sessionSlots.d.ts +9 -0
  74. package/dist/settings.component.d.ts +134 -8
  75. package/dist/sidebarI18n.d.ts +9 -0
  76. package/dist/sidebarLocales.d.ts +1 -0
  77. package/dist/status.service.d.ts +30 -2
  78. package/dist/statusLine.d.ts +27 -0
  79. package/dist/update.d.ts +19 -5
  80. package/dist/update.service.d.ts +29 -20
  81. package/dist/viewPanel.d.ts +13 -3
  82. package/dist/viewer.d.ts +2 -0
  83. package/hooks/agentdeck-codex-notify.ps1 +28 -25
  84. package/hooks/agentdeck-label.js +53 -53
  85. package/hooks/agentdeck-mailbox.mjs +103 -0
  86. package/hooks/agentdeck-notify.ps1 +43 -14
  87. package/hooks/agentdeck-status.ps1 +33 -33
  88. package/hooks/agentdeck-statusline.mjs +351 -0
  89. package/package.json +72 -68
  90. package/updater/agentdeck-update.ps1 +153 -130
  91. package/dist/index.js.map +0 -1
@@ -0,0 +1,22 @@
1
+ import { SavedAccount, AccountQuota } from './accounts';
2
+ import { MetaInput } from './meta';
3
+ export interface QuotaSnapshot {
4
+ values: AccountQuota[];
5
+ ts: number;
6
+ stale: boolean;
7
+ }
8
+ export declare function registerAccountSource(account: SavedAccount, home?: string): void;
9
+ /** Select only identity-checked credentials. A newer live CLI token wins over an old private copy. */
10
+ export declare function synchronizeClaudeAuth(account: SavedAccount): string;
11
+ export declare function ensureAccountSession(account: SavedAccount, forceRefresh?: boolean): Promise<void>;
12
+ export declare function cachedAccountQuotas(account: SavedAccount): QuotaSnapshot | null;
13
+ export declare function recordAccountUsage(account: SavedAccount, meta: MetaInput & {
14
+ ts?: number;
15
+ configDir?: string;
16
+ }): void;
17
+ export declare function getAccountQuotas(account: SavedAccount): Promise<QuotaSnapshot>;
18
+ /** Runs without opening login windows or issuing usage requests; the CLI remains the live source of truth. */
19
+ export declare function maintainAccountSessions(metas?: (MetaInput & {
20
+ ts?: number;
21
+ configDir?: string;
22
+ })[]): Promise<void>;
@@ -0,0 +1,50 @@
1
+ /// <reference types="node" />
2
+ export type AccountProvider = 'claude' | 'codex';
3
+ export interface SavedAccount {
4
+ provider: AccountProvider;
5
+ key: string;
6
+ name: string;
7
+ id: string;
8
+ }
9
+ export interface AccountQuota {
10
+ label: string;
11
+ remaining?: number;
12
+ status?: string;
13
+ resetsAt?: number;
14
+ }
15
+ export declare class AccountRequestError extends Error {
16
+ kind: 'auth' | 'temporary';
17
+ status: number;
18
+ retryAfterMs: number;
19
+ constructor(kind: 'auth' | 'temporary', message: string, status?: number, retryAfterMs?: number);
20
+ }
21
+ export declare const ACCOUNTS_FILE: string;
22
+ /** Do not let JSON parser errors (which can contain passwords) escape this boundary. */
23
+ export declare function readAccounts(file?: string): SavedAccount[];
24
+ export declare function accountHome(account: SavedAccount): string;
25
+ export declare function accountEnv(account: SavedAccount): NodeJS.ProcessEnv;
26
+ export declare function accountEmail(provider: AccountProvider, home: string): string;
27
+ /** Windows encrypts the snapshot for the current OS user; secrets travel over stdin, never argv. */
28
+ export declare function protectAccountAuth(value: string, decrypt?: boolean): Promise<string>;
29
+ export declare function saveAccountAuth(account: SavedAccount): Promise<void>;
30
+ export declare function restoreAccountAuth(account: SavedAccount): Promise<void>;
31
+ /** Clone settings, share only conversation/instruction directories, keep auth private per account. */
32
+ export declare function prepareAccount(account: SavedAccount, sourceHome?: string): void;
33
+ /** In-flight marketplace seeding for an account home (tests and callers that must wait). */
34
+ export declare function pendingMarketplaceSeed(dest: string): Promise<void>;
35
+ /**
36
+ * Codex keeps git marketplace clones in `<CODEX_HOME>/.tmp/marketplaces/<name>`. An account home starts
37
+ * without them, so Codex clones each configured marketplace itself; a large one hits Codex's 30s clone
38
+ * timeout, the half-cloned `.staging/marketplace-upgrade-*` is never removed, and the retry repeats about
39
+ * once a minute (~370MB each, 130GB observed 2026-09-18). Copy the clones the source home already has.
40
+ * Async so the account picker does not freeze; a partial copy never takes the final name.
41
+ */
42
+ export declare function seedCodexMarketplaces(source: string, dest: string): Promise<void>;
43
+ export declare function parseQuotas(provider: AccountProvider, body: any): AccountQuota[];
44
+ /** The app-server snapshot omits model_usage, which currently reports Astra availability, not a percentage. */
45
+ export declare function parseCodexUsage(body: any): AccountQuota[];
46
+ export declare function authenticateAccount(account: SavedAccount): Promise<void>;
47
+ export declare function fetchAccountQuotas(account: SavedAccount): Promise<AccountQuota[]>;
48
+ export type LoginBrowser = (url: string, account: SavedAccount, cancel: () => void) => Promise<() => void>;
49
+ /** First login is completed by the user; the saved authentication is reused afterwards. */
50
+ export declare function loginAccount(account: SavedAccount, browser: LoginBrowser): Promise<void>;
package/dist/agents.d.ts CHANGED
@@ -25,6 +25,21 @@ export interface AgentProfile {
25
25
  id: AgentId;
26
26
  /** 사람에게 보여줄 이름 (사이드바·진단에 쓴다) */
27
27
  label: string;
28
+ /**
29
+ * 사이드바 줄 머리에 붙일 표식 (인라인 SVG 원문).
30
+ *
31
+ * **문자 글리프가 아니라 SVG 인 이유** — 에이전트들이 스스로 쓰는 글리프는
32
+ * Claude `✳`·Gemini `✦` 처럼 둘 다 별 모양이라 12px 에서 형태로 갈리지 않는다
33
+ * (색만 다르면 색각 이상에서 구분이 사라진다). 형태(육각·별·6방 별표)와 색을
34
+ * 둘 다 다르게 주려면 도형을 직접 그려야 한다.
35
+ *
36
+ * 이 필드는 **상수 문자열이다** — 사용자 입력이 절대 섞이지 않으므로 읽는 쪽이
37
+ * `innerHTML` 로 넣어도 안전하다(`deck.service.ts` `renderTab`). 그래서 여기에는
38
+ * 상수만 넣고, 어떤 경우에도 런타임 값을 끼워 만들지 않는다.
39
+ *
40
+ * 빈 문자열이면 표식을 그리지 않는다(= 에이전트를 못 알아본 보통 셸 탭).
41
+ */
42
+ icon: string;
28
43
  /** 프로세스 이름/명령줄에서 이 에이전트를 알아보는 조각 (소문자 비교) */
29
44
  processHints: string[];
30
45
  /** 탭 제목에서 알아보는 조각 (소문자 비교) */
@@ -1,5 +1,28 @@
1
1
  export declare const CODEX_EVENTS: string[];
2
2
  export declare function codexHooksPath(): string;
3
+ /** Codex 가 훅 신뢰 상태를 적어 두는 곳 — `hooks.json` 과 **다른 파일**이다 */
4
+ export declare function codexConfigPath(): string;
5
+ /**
6
+ * Codex 가 **꺼 둔** 우리 훅 목록 (`config.toml` 의 `[hooks.state]`).
7
+ *
8
+ * **`hooks.json` 에 우리 항목이 있다고 훅이 도는 것이 아니다.** Codex 는 훅을 처음 보면
9
+ * `/hooks` 에서 사람이 신뢰할 때까지 멈춰 두고, 그 결과를 `config.toml` 에 따로 적는다:
10
+ *
11
+ * [hooks.state.'C:\\Users\\…\\hooks.json:user_prompt_submit:0:0']
12
+ * trusted_hash = "sha256:…"
13
+ * enabled = false
14
+ *
15
+ * 2026-09-14 실측: 이 PC 는 `session_start`·`user_prompt_submit`·`stop` 셋이 꺼져 있었고,
16
+ * 그 셋이 정확히 **진행중 진입과 완료 신호**라 사이드바가 Codex 상태를 영영 못 받았다
17
+ * (상태 보고 폴더에 codex 파일 0건). 설치만 확인하고 "연동됨" 이라 말하면 사용자는
18
+ * 아무 일도 안 일어나는 이유를 볼 수 없다 — 그래서 이 값을 따로 읽어 화면에 말한다.
19
+ *
20
+ * TOML 파서를 들이지 않는 이유 — 읽는 것이 **한 종류의 줄**뿐이고, 그 모양이 깨지면
21
+ * 빈 목록으로 떨어져 "모른다" 가 된다(없는 경고를 지어내지 않는다).
22
+ */
23
+ export declare function codexDisabledEvents(): string[];
24
+ /** `user_prompt_submit` → `UserPromptSubmit` (config.toml 은 snake_case, hooks.json 은 PascalCase) */
25
+ export declare function codexEventLabel(snake: string): string;
3
26
  export declare function stripCodexHooks(settings: any): any;
4
27
  export declare function mergeCodexHooks(settings: any, script: string): any;
5
28
  export declare function codexHooksInstalled(): boolean;
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Codex 세션 기록(rollout jsonl)에서 "지금 이 탭" 줄에 쓸 값을 뽑는다.
3
+ *
4
+ * **왜 다른 경로인가** — Claude Code 는 `statusLine` 이라는 통보 창구가 있어 그쪽 입력을 베끼면
5
+ * 되지만(`hooks/agentdeck-statusline.mjs`), Codex 에는 그런 것이 없다. 대신 Codex 는 자기 세션
6
+ * 기록에 같은 값을 남긴다(2026-09-14 실측, `~/.codex/sessions/…/rollout-*.jsonl`):
7
+ *
8
+ * `turn_context` → `model: "gpt-6-astra"` · `effort: "low"` (턴마다 새로 나온다)
9
+ * `session_meta` → `cwd` · `cli_version` (+ 옛 버전은 `context_window` 가 **숫자**)
10
+ * `event_msg`/`token_count` → `rate_limits.primary/secondary` (`used_percent`·`window_minutes`·`resets_at`)
11
+ * `info.last_token_usage.total_tokens` · `info.model_context_window`
12
+ *
13
+ * **창 크기가 사는 곳이 버전마다 다르다.** 0.154.0 부터 `session_meta.context_window` 는 숫자가
14
+ * 아니라 `{window_id: "…"}` 객체이고, 진짜 토큰 수는 `token_count.info.model_context_window` 로
15
+ * 옮겨 갔다 (2026-09-14 실측, gpt-6-astra / cli 0.154.0: `{"window_id":"01a09f5e-…"}` 와 `258400`).
16
+ * 그래서 둘 다 읽는다 — 하나만 읽으면 그 버전에서 컨텍스트% 칸이 통째로 사라진다.
17
+ *
18
+ * **이 파일은 순수하다** — fs·DOM·tabby 를 건드리지 않는다(`agents.ts`·`meta.ts` 와 같은 규칙).
19
+ * 줄을 먹이면 상태가 갱신되고, 서비스 쪽은 파일을 증분으로 읽어 그 줄만 넘긴다.
20
+ */
21
+ /** 한도 한 칸 — Codex 는 창 길이를 분으로 준다 */
22
+ export interface CodexWindow {
23
+ pct: number;
24
+ /** 창 길이(분). 300 = 5시간, 10080 = 7일 */
25
+ windowMinutes: number;
26
+ /** 리셋 시각 (epoch **초**) */
27
+ resetsAt: number;
28
+ }
29
+ export interface CodexState {
30
+ model: string;
31
+ effort: string;
32
+ cwd: string;
33
+ cliVersion: string;
34
+ /**
35
+ * 세션의 컨텍스트 창 크기(토큰). Codex 가 안 적어 주는 버전도 있다.
36
+ * 0.154.0 부터는 `session_meta` 가 아니라 `token_count.info.model_context_window` 가 원천이다
37
+ */
38
+ contextWindow: number;
39
+ /** 마지막 요청이 쓴 토큰 — 컨텍스트 사용률의 분자 */
40
+ lastTokens: number;
41
+ primary: CodexWindow | null;
42
+ secondary: CodexWindow | null;
43
+ /**
44
+ * 개행으로 끝나지 않은 마지막 조각 — 다음 청크 앞에 이어 붙인다.
45
+ *
46
+ * **증분 읽기에는 이게 반드시 있어야 한다.** 서비스는 2초마다 `size - lastSize` 만큼 읽는데
47
+ * Codex 는 그동안에도 쓰고 있어 읽은 청크의 마지막 줄은 대개 미완성이다. 이어 붙이지 않으면
48
+ * 그 줄을 버리는데 `lastSize` 는 이미 전진했으므로 **나머지 절반도 다음 판에서 버려진다** —
49
+ * 턴 끝의 마지막 `token_count`(한도·컨텍스트%)가 통째로 유실돼 값이 옛 상태로 굳는다
50
+ * (2026-09-15 코드리뷰 지적). `subagents.ts` 의 `feedChunk` 가 같은 이유로 같은 것을 한다.
51
+ */
52
+ pending: string;
53
+ /** 먹인 줄 수 / 버린 줄 수 (진단용) */
54
+ lines: number;
55
+ skipped: number;
56
+ /** `MAX_PENDING` 을 넘겨 버린 꼬리 수 (진단용 — 0 이 아니면 뭔가 이상하다) */
57
+ dropped: number;
58
+ }
59
+ export declare function createCodexState(): CodexState;
60
+ /**
61
+ * 줄 하나를 먹인다. **마지막 값이 이긴다** — `turn_context` 는 턴마다, `token_count` 는 요청마다
62
+ * 새로 나오므로 나중 줄이 지금 상태다. 못 읽는 줄은 세기만 하고 버린다(증분 읽기의 반쪽 줄).
63
+ */
64
+ export declare function feedCodexLine(state: CodexState, line: string): void;
65
+ export declare function feedCodexChunk(state: CodexState, chunk: string): void;
66
+ /** 컨텍스트 사용률(%) — 창 크기를 모르면 null (지어내지 않는다) */
67
+ export declare function codexContextPct(state: CodexState): number | null;
68
+ /**
69
+ * 한도 두 칸을 Claude 쪽과 **같은 자리**(5시간/7일)에 맞춘다.
70
+ *
71
+ * Codex 는 이름 대신 창 길이(분)를 주므로 그 값으로 가른다 — 실측은 `primary: 300분`(5시간),
72
+ * `secondary: 10080분`(7일)이다. 길이가 그 둘이 아니면 **넣지 않는다**: 다른 길이의 값을 `5h` 자리에
73
+ * 그리면 화면이 거짓말을 한다.
74
+ */
75
+ export declare function codexLimits(state: CodexState): {
76
+ fiveHourPct: number | null;
77
+ fiveHourResetsAt: number;
78
+ sevenDayPct: number | null;
79
+ sevenDayResetsAt: number;
80
+ };
81
+ /**
82
+ * Codex 계정 메일 — `~/.codex/auth.json` 의 `tokens.id_token`(JWT) 가운데 조각에 들어 있다.
83
+ *
84
+ * **서명을 확인하지 않는다.** 이건 인증이 아니라 "지금 이 컴퓨터가 누구로 로그인돼 있나" 를
85
+ * 화면에 적기 위한 읽기다. 토큰 자체는 어디에도 싣지 않는다.
86
+ */
87
+ export declare function emailFromIdToken(jwt: string | null | undefined): string;
package/dist/config.d.ts CHANGED
@@ -134,6 +134,14 @@ export declare class AgentDeckConfigProvider extends ConfigProvider {
134
134
  * 설정 창에서 토글한다 (recovery.service.ts).
135
135
  */
136
136
  noTabRecovery: boolean;
137
+ /**
138
+ * 개발자 옵션 — `dist/index.js` 가 바뀌면 세션을 살린 채 창을 리로드한다(devReload.service.ts).
139
+ *
140
+ * **개발 빌드 + 개발 설치(소스 트리)에서만 의미가 있다.** npm 배포 빌드(`npm pack` →
141
+ * `build:release`)는 기능 코드를 스텁으로 바꿔 끼우므로 이 값이 참이어도 아무것도 안 하고
142
+ * 설정 화면에도 안 보인다.
143
+ */
144
+ devMode: boolean;
137
145
  /**
138
146
  * 기동할 때 npm 레지스트리를 보고 **새 버전을 받아 둔다** (적용은 다음 기동).
139
147
  *
@@ -153,6 +161,26 @@ export declare class AgentDeckConfigProvider extends ConfigProvider {
153
161
  updateRegistry: string;
154
162
  /** PTY 출력이 이 시간(ms) 이상 없으면 running -> idle */
155
163
  idleAfterMs: number;
164
+ /**
165
+ * **훅이 고정한 `진행중` 탭**이 이 시간(ms) 동안 아무 기척도 없으면 고정을 풀고 idle 로
166
+ * 내린다. 0 이면 끈다 (0.17.0 이전 동작 — 영영 안 내려온다).
167
+ *
168
+ * 왜 따로 두나 — 위 `idleAfterMs`(2.5초)는 **자동 감지** 탭의 값이라 고정된 탭에 쓸 수
169
+ * 없다. 훅은 도구 하나가 끝날 때(`PostToolUse`)에야 말하므로 2분짜리 빌드 중에는 몇 분씩
170
+ * 조용하고, 그 값을 그대로 적용하면 일하는 탭이 매번 idle 로 깜빡인다.
171
+ *
172
+ * 왜 필요한가 — 훅에 "세션이 끝났다" 이벤트가 없다(`claudeHooks.ts` PLAN). Ctrl+C 로 끊거나
173
+ * 창을 닫거나 CLI 가 죽으면 마지막 `running` 이 그대로 남고, 고정된 탭에는 배지가 내려올
174
+ * 길이 하나도 없었다 (`status.service.ts tickIdle` 주석). 사이드바가 "작업중" 이라고
175
+ * 말하는데 실은 아무것도 안 하고 있는 탭이 그것이다.
176
+ *
177
+ * 5분인 이유 — 기척으로 **훅 보고·PTY 출력·작업중 신호 셋 다** 인정하므로(셋 중 최신에서
178
+ * 잰다) 살아 있는 세션은 이 값에 걸릴 일이 없다. 사람이 "어? 안 바뀌네" 하고 알아채는
179
+ * 시간보다는 짧아야 해서 시간 단위로 두지 않았다.
180
+ *
181
+ * `승인대기`·`한도`는 이 시계를 타지 않는다 — 조용한 것이 정상인 상태다
182
+ */
183
+ staleAfterMs: number;
156
184
  /** 출력 패턴으로 상태를 자동 추론할지 */
157
185
  autoDetect: boolean;
158
186
  /** 사이드바에 경과 시간 표시 */
@@ -172,6 +200,15 @@ export declare class AgentDeckConfigProvider extends ConfigProvider {
172
200
  * (`notify.service` `scanSubagents`).
173
201
  */
174
202
  subagentCount: boolean;
203
+ /**
204
+ * 사이드바 하단에 **지금 이 탭** 줄을 고정한다 — 도는 모델·effort·계정·컨텍스트%·
205
+ * 5h/7d 한도%. 탭을 바꾸면 그 탭 값으로 다시 그린다.
206
+ *
207
+ * 켜 두는 것만으로는 아무 일도 일어나지 않는다 — 이 값들은 **statusLine stdin 에만**
208
+ * 내려오므로 설정 창에서 `statusLine 연결` 을 설치해야 보고가 온다(statusLine.ts).
209
+ * 설치 전에는 줄이 통째로 접혀 있어 화면이 지금과 같다.
210
+ */
211
+ metaLine: boolean;
175
212
  /**
176
213
  * 사이드바 탭을 상태 우선순위(waiting → error → running → done → idle)로 정렬한다.
177
214
  * 같은 상태끼리는 탭 순서를 지킨다. 기본은 끔 — 순정 탭바와 같은 탭 순서로 보인다.
@@ -194,7 +231,7 @@ export declare class AgentDeckConfigProvider extends ConfigProvider {
194
231
  */
195
232
  searchBox: boolean;
196
233
  /**
197
- * 사이드바를 **키보드로** 다룬다 — 핫키(`agentdeck-focus-list`, 기본 `Ctrl-Shift-L`)로
234
+ * 사이드바를 **키보드로** 다룬다 — 핫키(`agentdeck-focus-list`, 기본 `Ctrl-L`)로
198
235
  * 목록에 들어가 ↑↓ 로 훑고, Enter 로 그 탭으로 전환, Esc 로 터미널에 돌아온다.
199
236
  * 검색창에서 ↓ 를 누르면 결과 목록으로 내려가고, 첫 줄에서 ↑ 면 검색창으로 돌아온다.
200
237
  * 그룹 헤더도 지나가며 Enter 로 접었다 펼 수 있다.
@@ -272,11 +309,20 @@ export declare class AgentDeckConfigProvider extends ConfigProvider {
272
309
  * UUID 목록에서 자기 작업을 찾는 것이라 **라벨을 붙여 보여주는 것** 이 이 기능의 전부다.
273
310
  */
274
311
  resumeList: boolean;
275
- /** 그룹당 몇 줄까지 보여줄지. 0 이면 제한 없음 (목록이 길어지면 살아 있는 탭이 밀린다) */
312
+ /**
313
+ * 몇 줄까지 보여줄지. **0 = 제한 없음이고 그게 기본이다.**
314
+ *
315
+ * 예전에는 5 였다 — 서랍이 그룹마다 목록 **안**에 있어서, 길어지면 살아 있는 탭이
316
+ * 아래로 밀려났기 때문이다. 지금 서랍은 사이드바 바닥에 붙은 **스크롤 상자**라
317
+ * 몇 줄이 들어 있든 살아 있는 탭을 밀지 않는다. 잘라 둘 이유가 사라졌고,
318
+ * 잘려 나간 세션은 사람이 찾을 방법이 아예 없었다
319
+ * (2026-09-14 유저: "기껏 저장한걸 굳이 안쓸 이유는 없을 듯").
320
+ */
276
321
  resumeListLimit: number;
277
322
  /**
278
323
  * 며칠치까지. 기간 밖 세션은 **화면에서만** 빠지고 원장·기록은 그대로다.
279
- * stat 단계에서 잘라내므로 이 값이 작을수록 펼치는 순간이 싸다.
324
+ * 위와 같은 이유로 0(제한 없음)이 기본이다 — 한 달 전 작업을 이어받는 일이
325
+ * 드물긴 해도, 드물다는 것이 "못 찾게 한다" 의 근거는 아니다.
280
326
  */
281
327
  resumeListDays: number;
282
328
  /** 지난 세션 줄을 펼쳐 둔 그룹 키 (`collapsedGroups` 와 반대로 **펼침**을 적는다 — 기본이 접힘이라서) */
@@ -309,6 +355,25 @@ export declare class AgentDeckConfigProvider extends ConfigProvider {
309
355
  * false 로 두면 터미널 앱에 리터럴 Ctrl+V(0x16, quoted-insert)를 보낼 수 있다
310
356
  */
311
357
  claimCtrlV: boolean;
358
+ /**
359
+ * `Ctrl+T`(⌘+T) 를 새 탭이 받는다. 순정 `new-tab`에 겹치는 키만 뗀다.
360
+ * false 면 떼지 않고 우리 핫키도 무시한다(순정 그대로). 순정 새 탭은 기본 프로필로 열어
361
+ * 훅이 탭을 못 찾으므로, 이 플러그인을 쓰는 동안은 켜 두는 것이 맞다
362
+ */
363
+ claimNewTabKey: boolean;
364
+ /**
365
+ * `Ctrl+R`을 화면 복구가 받는다. 순정 `rename-tab`에 겹치는 키만 뗀다.
366
+ * false 면 떼지 않고 우리 핫키도 무시한다(순정 그대로). 탭 이름은 사이드바 더블클릭으로 바꾼다
367
+ */
368
+ claimRepairKey: boolean;
369
+ /**
370
+ * 순정 `close-pane`(포커스된 분할 패널 닫기)이 **비어 있으면** 이 키를 채운다.
371
+ * Tabby 기본표는 이 항목이 빈 채로 오고, agentdeck 은 짧은 우클릭을 복사/붙여넣기로
372
+ * 쓰기 때문에 컨텍스트 메뉴로 패널을 닫기가 번거롭다. `Ctrl-Q` 는 순정 네 패키지
373
+ * 기본표·agentdeck 어디에도 없는 키(2026-09-16 grep 0건).
374
+ * 이미 사람이 채워 둔 표는 건드리지 않는다. 빈 문자열이면 아무것도 하지 않는다.
375
+ */
376
+ closePaneKey: string;
312
377
  /**
313
378
  * Shift+Enter / Ctrl+Enter 를 캡처 단계에서 직접 줄바꿈으로 처리한다.
314
379
  *
@@ -623,12 +688,53 @@ export declare class AgentDeckConfigProvider extends ConfigProvider {
623
688
  *
624
689
  * 기본값을 비워 두지 않은 이유 — 이것이 사이드바를 마우스 없이 만지는 **유일한
625
690
  * 진입점**이라(목록은 tabindex=-1, `wireListKeys`) 안 묶여 있으면 기능이 없는 것과
626
- * 같다. `Ctrl-Shift-L` 은 Tabby 순정 기본 핫키와 겹치지 않는다 — core·terminal·
691
+ * 같다. `Ctrl-L` 은 Tabby 순정 기본 핫키와 겹치지 않는다 — core·terminal·
627
692
  * local·settings 네 패키지의 기본 조합을 훑어 확인했다(2026-09-09):
628
693
  * 그쪽이 쓰는 것은 `Ctrl-Shift-{A,C,D,E,F,I,P,R,S,T,V,W,Z}`·방향키·Tab·PageUp/Down·
629
694
  * Backspace·`-` 이다. 다른 플러그인과 부딪히면 설정 창에서 바꾼다.
630
695
  */
631
696
  'agentdeck-focus-list': string[];
697
+ /**
698
+ * **사이드바에 보이는 순서로** N 번째 세션으로 건너뛴다 (`Ctrl-1` … `Ctrl-9`).
699
+ *
700
+ * Tabby 순정 `tab-1…tab-10` 과 다른 기능이다 — 그쪽은 `app.tabs`(탭 바의 순서)를 세고
701
+ * 이쪽은 **사이드바 화면에 보이는 줄**을 센다. 정렬(`sortByStatus`)·그룹·검색·상태 필터가
702
+ * 걸리면 둘은 어긋나고, 사람이 보고 있는 것은 사이드바다.
703
+ *
704
+ * 기본값이 `Ctrl-N` 인 근거 — Tabby 의 Windows/Linux 기본은 `tab-N` = `Alt-N` 이라
705
+ * 겹치지 않는다(`tabby-core` 의 windows/linux 기본 핫키표). macOS 기본은 `⌘-N` 이라
706
+ * 역시 겹치지 않는다. 터미널 쪽도 `Ctrl+숫자`는 제어문자를 내지 않으므로 뺏어도 잃는 키가
707
+ * 없다.
708
+ *
709
+ * 9 까지만 두는 이유 — 열 번째부터는 눈으로 세는 것이 키를 누르는 것보다 느리다.
710
+ * 그 위는 `Ctrl-L` 로 목록에 들어가 ↑↓ 로 간다
711
+ */
712
+ 'agentdeck-jump-1': string[];
713
+ 'agentdeck-jump-2': string[];
714
+ 'agentdeck-jump-3': string[];
715
+ 'agentdeck-jump-4': string[];
716
+ 'agentdeck-jump-5': string[];
717
+ 'agentdeck-jump-6': string[];
718
+ 'agentdeck-jump-7': string[];
719
+ 'agentdeck-jump-8': string[];
720
+ 'agentdeck-jump-9': string[];
721
+ /**
722
+ * Common actions use Ctrl without Shift. Existing custom shortcuts remain saved.
723
+ * Stock new-tab/rename-tab bindings are removed only when they overlap ours.
724
+ */
725
+ 'agentdeck-new-tab': string[];
726
+ 'agentdeck-view': string[];
727
+ /** 패널의 파일 ↔ 변경 전환 — 기본은 미배정 (설정 창 단축키 절에서 매긴다) */
728
+ 'agentdeck-view-mode': any[];
729
+ 'agentdeck-repair': string[];
632
730
  };
633
731
  };
634
732
  }
733
+ /**
734
+ * 우리 기본 핫키 표 — 설정 창 **단축키** 절의 `기본값` 버튼이 쓴다.
735
+ *
736
+ * `defaults` 는 인스턴스 필드라 클래스에서 바로 못 읽는다. ConfigProvider 는 생성자 의존이
737
+ * 없으므로 하나 만들어 꺼내는 것이 가장 싸다. 순정 `close-pane` 은 우리 표에 없고
738
+ * `agentDeck.closePaneKey` 가 원천이라 여기서 함께 얹는다(`ensureClosePaneHotkey` 와 같은 값).
739
+ */
740
+ export declare function defaultHotkeys(): Record<string, string[]>;
@@ -3,7 +3,39 @@ export declare class CursorVisibilityStream {
3
3
  corrections: number;
4
4
  write(data: string, enabled: boolean): string;
5
5
  }
6
+ /**
7
+ * `CSI Ps SP q` (DECSCUSR) 의 **깜빡이는 스타일을 고정 스타일로** 바꾼다.
8
+ *
9
+ * Codex 0.154.0 은 프레임마다 `ESC [ 0 q` 를 보낸다(`test/cursor.cjs` 의 실측 `lastPacket`).
10
+ * 0 은 "깜빡이는 블록" 이라, 터미널은 시킨 대로 커서를 깜빡인다 — **순정 Tabby 에서도 똑같이
11
+ * 난다**(2026-09-15 유저 확인). 표시/숨김이 아니라 스타일이므로 가시성 필터로는 막을 수 없다.
12
+ *
13
+ * 모양은 그대로 두고 깜빡임만 끈다: 0·1(블록)→2, 3(밑줄)→4, 5(막대)→6.
14
+ */
15
+ export declare class SteadyCursorStyleStream {
16
+ private pending;
17
+ changes: number;
18
+ write(data: string, enabled: boolean): string;
19
+ }
6
20
  /** Install at the frontend's write boundary; do not inject into xterm's
7
21
  * asynchronously parsed stream or touch the application's saved cursor slot.
8
22
  */
9
- export declare function installCursorVisibilityFix(frontend: any, enabled: (data: string) => boolean, onCorrection: () => void): void;
23
+ export declare function installCursorVisibilityFix(frontend: any, enabled: (data: string) => boolean, onCorrection: () => void, onTrace?: (summary: string) => void): void;
24
+ /** ConPTY wraps **every** redraw chunk with DECTCEM hide/show while Codex is
25
+ * still painting. Those toggles are noise, not intent — forwarding them makes the
26
+ * cursor flicker at the redraw rate (2026-09-15 measured: the cursor cell flipped
27
+ * every 100-200ms, 5-10 Hz, during Codex's startup animation).
28
+ *
29
+ * So strip them and keep only the application's **latest intent**. The installer
30
+ * applies a visibility change to the terminal *only when that intent differs from
31
+ * what is already on screen*, so a steady cursor stays steady. Text and position
32
+ * commands pass through untouched.
33
+ */
34
+ export declare class StableCursorStream {
35
+ private pending;
36
+ /** 애플리케이션이 마지막으로 말한 의도 — **화면 상태가 아니다** (그건 설치부가 쥔다) */
37
+ visible: boolean;
38
+ /** 걷어낸 표시 명령 수 (진단용) */
39
+ deferredShows: number;
40
+ write(data: string, enabled: boolean): string;
41
+ }