@caoruhua/open-claude-remote 1.0.9 → 1.3.7

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 (99) hide show
  1. package/README.md +48 -27
  2. package/dist/backend/src/api/file-routes.d.ts +0 -24
  3. package/dist/backend/src/api/file-routes.d.ts.map +1 -1
  4. package/dist/backend/src/api/file-routes.js +464 -68
  5. package/dist/backend/src/api/file-routes.js.map +1 -1
  6. package/dist/backend/src/api/instance-routes.d.ts +4 -0
  7. package/dist/backend/src/api/instance-routes.d.ts.map +1 -1
  8. package/dist/backend/src/api/instance-routes.js +27 -2
  9. package/dist/backend/src/api/instance-routes.js.map +1 -1
  10. package/dist/backend/src/cli-utils.d.ts +2 -0
  11. package/dist/backend/src/cli-utils.d.ts.map +1 -1
  12. package/dist/backend/src/cli-utils.js +11 -1
  13. package/dist/backend/src/cli-utils.js.map +1 -1
  14. package/dist/backend/src/cli.d.ts +6 -0
  15. package/dist/backend/src/cli.d.ts.map +1 -1
  16. package/dist/backend/src/cli.js +73 -10
  17. package/dist/backend/src/cli.js.map +1 -1
  18. package/dist/backend/src/config.d.ts +11 -0
  19. package/dist/backend/src/config.d.ts.map +1 -1
  20. package/dist/backend/src/config.js +36 -1
  21. package/dist/backend/src/config.js.map +1 -1
  22. package/dist/backend/src/daemon/daemon-client.d.ts +1 -0
  23. package/dist/backend/src/daemon/daemon-client.d.ts.map +1 -1
  24. package/dist/backend/src/daemon/daemon-client.js +1 -0
  25. package/dist/backend/src/daemon/daemon-client.js.map +1 -1
  26. package/dist/backend/src/daemon/daemon-entry.js +19 -6
  27. package/dist/backend/src/daemon/daemon-entry.js.map +1 -1
  28. package/dist/backend/src/daemon/daemon-launcher.d.ts.map +1 -1
  29. package/dist/backend/src/daemon/daemon-launcher.js +4 -1
  30. package/dist/backend/src/daemon/daemon-launcher.js.map +1 -1
  31. package/dist/backend/src/daemon/restart-state.d.ts +1 -0
  32. package/dist/backend/src/daemon/restart-state.d.ts.map +1 -1
  33. package/dist/backend/src/daemon/restart-state.js.map +1 -1
  34. package/dist/backend/src/deps/detector.js +1 -1
  35. package/dist/backend/src/deps/index.d.ts +1 -1
  36. package/dist/backend/src/deps/index.js +22 -22
  37. package/dist/backend/src/deps/installer.js +6 -6
  38. package/dist/backend/src/deps/installer.js.map +1 -1
  39. package/dist/backend/src/deps/types.d.ts +1 -1
  40. package/dist/backend/src/deps/types.d.ts.map +1 -1
  41. package/dist/backend/src/deps/types.js +9 -11
  42. package/dist/backend/src/deps/types.js.map +1 -1
  43. package/dist/backend/src/index.d.ts.map +1 -1
  44. package/dist/backend/src/index.js +29 -6
  45. package/dist/backend/src/index.js.map +1 -1
  46. package/dist/backend/src/instance/instance-manager.d.ts +4 -0
  47. package/dist/backend/src/instance/instance-manager.d.ts.map +1 -1
  48. package/dist/backend/src/instance/instance-manager.js +30 -7
  49. package/dist/backend/src/instance/instance-manager.js.map +1 -1
  50. package/dist/backend/src/instance/instance-session.d.ts +6 -1
  51. package/dist/backend/src/instance/instance-session.d.ts.map +1 -1
  52. package/dist/backend/src/instance/instance-session.js +9 -3
  53. package/dist/backend/src/instance/instance-session.js.map +1 -1
  54. package/dist/backend/src/instance/types.d.ts +1 -0
  55. package/dist/backend/src/instance/types.d.ts.map +1 -1
  56. package/dist/backend/src/pty/fix-pty-permissions.d.ts +1 -1
  57. package/dist/backend/src/pty/fix-pty-permissions.js +1 -1
  58. package/dist/backend/src/pty/output-buffer.d.ts +6 -0
  59. package/dist/backend/src/pty/output-buffer.d.ts.map +1 -1
  60. package/dist/backend/src/pty/output-buffer.js +10 -0
  61. package/dist/backend/src/pty/output-buffer.js.map +1 -1
  62. package/dist/backend/src/registry/stop-instances.js +1 -1
  63. package/dist/backend/src/services/pptx-converter.d.ts +66 -0
  64. package/dist/backend/src/services/pptx-converter.d.ts.map +1 -0
  65. package/dist/backend/src/services/pptx-converter.js +282 -0
  66. package/dist/backend/src/services/pptx-converter.js.map +1 -0
  67. package/dist/backend/src/update.d.ts +2 -2
  68. package/dist/backend/src/update.d.ts.map +1 -1
  69. package/dist/backend/src/update.js +9 -9
  70. package/dist/backend/src/update.js.map +1 -1
  71. package/dist/backend/src/utils/banner.d.ts +2 -0
  72. package/dist/backend/src/utils/banner.d.ts.map +1 -1
  73. package/dist/backend/src/utils/banner.js +2 -1
  74. package/dist/backend/src/utils/banner.js.map +1 -1
  75. package/dist/backend/src/utils/network.d.ts +22 -0
  76. package/dist/backend/src/utils/network.d.ts.map +1 -1
  77. package/dist/backend/src/utils/network.js +54 -0
  78. package/dist/backend/src/utils/network.js.map +1 -1
  79. package/dist/shared/file-types.d.ts +176 -0
  80. package/dist/shared/file-types.d.ts.map +1 -0
  81. package/dist/shared/file-types.js +108 -0
  82. package/dist/shared/file-types.js.map +1 -0
  83. package/dist/shared/index.d.ts +1 -0
  84. package/dist/shared/index.d.ts.map +1 -1
  85. package/dist/shared/index.js +1 -0
  86. package/dist/shared/index.js.map +1 -1
  87. package/dist/shared/instance.d.ts +2 -0
  88. package/dist/shared/instance.d.ts.map +1 -1
  89. package/dist/shared/instance.js.map +1 -1
  90. package/frontend-dist/assets/{index-UXAwH56Q.css → index-BY0fnkbW.css} +1 -1
  91. package/frontend-dist/assets/index-qwSai8-t.js +211 -0
  92. package/frontend-dist/index.html +2 -2
  93. package/package.json +8 -4
  94. package/scripts/build.sh +3 -9
  95. package/scripts/dev.sh +1 -4
  96. package/scripts/git-hooks/pre-commit +0 -4
  97. package/scripts/publish-npm.sh +61 -0
  98. package/scripts/stop.sh +1 -1
  99. package/frontend-dist/assets/index-CVRtrLyp.js +0 -199
@@ -0,0 +1,176 @@
1
+ /**
2
+ * 文件类型系统 - 前后端共享
3
+ *
4
+ * 定义通用文件类型、目录结构和 API 响应格式
5
+ * 支持 Markdown、PDF、PPTX、图片等多种文件类型
6
+ */
7
+ /** 文件分类 */
8
+ export type FileCategory = 'markdown' | 'pdf' | 'presentation' | 'image' | 'all';
9
+ /** 文件类型图标映射 */
10
+ export declare const FILE_TYPE_ICONS: Record<FileCategory, string>;
11
+ /** 文件类型标签映射 */
12
+ export declare const FILE_TYPE_LABELS: Record<FileCategory, string>;
13
+ /** 文件扩展名到分类的映射 */
14
+ export declare const EXT_TO_CATEGORY: Record<string, FileCategory>;
15
+ /** MIME 类型映射 */
16
+ export declare const FILE_MIME_TYPES: Record<string, string>;
17
+ /** 支持的文件扩展名列表 */
18
+ export declare const SUPPORTED_EXTENSIONS: string[];
19
+ /** 图片扩展名列表 */
20
+ export declare const IMAGE_EXTENSIONS: string[];
21
+ /** 文档扩展名列表(支持预览的) */
22
+ export declare const PREVIEWABLE_EXTENSIONS: string[];
23
+ /** 可转换为 PDF 的扩展名 */
24
+ export declare const CONVERTIBLE_TO_PDF: string[];
25
+ /**
26
+ * 获取文件分类
27
+ * @param filename - 文件名
28
+ * @returns 文件分类
29
+ */
30
+ export declare function getFileCategory(filename: string): FileCategory;
31
+ /**
32
+ * 获取文件 MIME 类型
33
+ * @param filename - 文件名
34
+ * @returns MIME 类型
35
+ */
36
+ export declare function getFileMimeType(filename: string): string;
37
+ /**
38
+ * 检查文件是否可预览
39
+ * @param filename - 文件名
40
+ * @returns 是否可预览
41
+ */
42
+ export declare function isPreviewable(filename: string): boolean;
43
+ /**
44
+ * 检查文件是否可转换为 PDF
45
+ * @param filename - 文件名
46
+ * @returns 是否可转换
47
+ */
48
+ export declare function isConvertibleToPdf(filename: string): boolean;
49
+ /**
50
+ * 检查文件是否为图片
51
+ * @param filename - 文件名
52
+ * @returns 是否为图片
53
+ */
54
+ export declare function isImage(filename: string): boolean;
55
+ /** 通用文件信息项(前后端共享) */
56
+ export interface FileItem {
57
+ /** 文件名 */
58
+ filename: string;
59
+ /** 绝对路径 */
60
+ absolutePath: string;
61
+ /** 相对路径 */
62
+ relativePath: string;
63
+ /** 文件大小(字节) */
64
+ size: number;
65
+ /** 修改时间(ISO 格式) */
66
+ modifiedAt: string;
67
+ /** 文件分类 */
68
+ category: FileCategory;
69
+ /** 文件扩展名 */
70
+ extension: string;
71
+ }
72
+ /** 目录树节点 */
73
+ export interface DirectoryNode {
74
+ /** 目录名 */
75
+ name: string;
76
+ /** 完整路径 */
77
+ path: string;
78
+ /** 相对路径 */
79
+ relativePath: string;
80
+ /** 子目录 */
81
+ children: DirectoryNode[];
82
+ /** 目录中的文件数量 */
83
+ fileCount: number;
84
+ /** 按类型统计的文件数量 */
85
+ typeCounts: Record<FileCategory, number>;
86
+ }
87
+ /** 文件列表响应 */
88
+ export interface FileListResponse {
89
+ /** 文件列表 */
90
+ files: FileItem[];
91
+ /** 当前工作目录 */
92
+ cwd: string;
93
+ /** 文件总数 */
94
+ total: number;
95
+ /** 目录树结构 */
96
+ directoryTree?: DirectoryNode;
97
+ /** 按类型统计 */
98
+ typeCounts?: Record<FileCategory, number>;
99
+ }
100
+ /** 文件内容响应 */
101
+ export interface FileContentResponse {
102
+ /** 文件内容(文本)或 base64(二进制) */
103
+ content: string;
104
+ /** 文件路径(绝对路径) */
105
+ path: string;
106
+ /** 文件名 */
107
+ filename: string;
108
+ /** 文件大小(字节) */
109
+ size: number;
110
+ /** 是否为 base64 编码 */
111
+ isBase64?: boolean;
112
+ /** MIME 类型 */
113
+ mimeType?: string;
114
+ }
115
+ /** 文件读取请求参数 */
116
+ export interface FileReadParams {
117
+ /** 文件路径 */
118
+ path: string;
119
+ /** 实例 ID(可选,用于解析相对路径) */
120
+ instanceId?: string;
121
+ }
122
+ /** 文件列表请求参数 */
123
+ export interface FileListParams {
124
+ /** 扫描目录(可选) */
125
+ cwd?: string;
126
+ /** 实例 ID(可选) */
127
+ instanceId?: string;
128
+ /** 文件分类筛选(可选) */
129
+ category?: FileCategory;
130
+ /** 搜索关键词(可选) */
131
+ search?: string;
132
+ }
133
+ /** 转换任务状态 */
134
+ export type ConversionStatus = 'pending' | 'converting' | 'completed' | 'failed';
135
+ /** PPTX 转换任务 */
136
+ export interface ConversionTask {
137
+ /** 任务 ID */
138
+ id: string;
139
+ /** 源文件路径 */
140
+ sourcePath: string;
141
+ /** 输出 PDF 路径 */
142
+ outputPath: string;
143
+ /** 任务状态 */
144
+ status: ConversionStatus;
145
+ /** 创建时间 */
146
+ createdAt: string;
147
+ /** 完成时间 */
148
+ completedAt?: string;
149
+ /** 错误信息 */
150
+ error?: string;
151
+ }
152
+ /** 转换任务响应 */
153
+ export interface ConversionResponse {
154
+ /** 任务 ID */
155
+ taskId: string;
156
+ /** 当前状态 */
157
+ status: ConversionStatus;
158
+ /** PDF 文件路径(转换完成时) */
159
+ pdfPath?: string;
160
+ /** 错误信息 */
161
+ error?: string;
162
+ }
163
+ /** 转换状态查询响应 */
164
+ export interface ConversionStatusResponse {
165
+ /** 任务 ID */
166
+ taskId: string;
167
+ /** 当前状态 */
168
+ status: ConversionStatus;
169
+ /** PDF 文件路径(转换完成时) */
170
+ pdfPath?: string;
171
+ /** 进度百分比(0-100) */
172
+ progress?: number;
173
+ /** 错误信息 */
174
+ error?: string;
175
+ }
176
+ //# sourceMappingURL=file-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-types.d.ts","sourceRoot":"","sources":["../../shared/file-types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * 文件类型系统 - 前后端共享
3
+ *
4
+ * 定义通用文件类型、目录结构和 API 响应格式
5
+ * 支持 Markdown、PDF、PPTX、图片等多种文件类型
6
+ */
7
+ /** 文件类型图标映射 */
8
+ export const FILE_TYPE_ICONS = {
9
+ markdown: '📝',
10
+ pdf: '📄',
11
+ presentation: '📊',
12
+ image: '🖼️',
13
+ all: '📁',
14
+ };
15
+ /** 文件类型标签映射 */
16
+ export const FILE_TYPE_LABELS = {
17
+ markdown: 'Markdown',
18
+ pdf: 'PDF',
19
+ presentation: 'Presentation',
20
+ image: 'Image',
21
+ all: 'All Files',
22
+ };
23
+ /** 文件扩展名到分类的映射 */
24
+ export const EXT_TO_CATEGORY = {
25
+ '.md': 'markdown',
26
+ '.markdown': 'markdown',
27
+ '.pdf': 'pdf',
28
+ '.pptx': 'presentation',
29
+ '.ppt': 'presentation',
30
+ '.png': 'image',
31
+ '.jpg': 'image',
32
+ '.jpeg': 'image',
33
+ '.gif': 'image',
34
+ '.webp': 'image',
35
+ '.svg': 'image',
36
+ '.bmp': 'image',
37
+ '.ico': 'image',
38
+ };
39
+ /** MIME 类型映射 */
40
+ export const FILE_MIME_TYPES = {
41
+ '.md': 'text/markdown',
42
+ '.markdown': 'text/markdown',
43
+ '.pdf': 'application/pdf',
44
+ '.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
45
+ '.ppt': 'application/vnd.ms-powerpoint',
46
+ '.png': 'image/png',
47
+ '.jpg': 'image/jpeg',
48
+ '.jpeg': 'image/jpeg',
49
+ '.gif': 'image/gif',
50
+ '.webp': 'image/webp',
51
+ '.svg': 'image/svg+xml',
52
+ '.bmp': 'image/bmp',
53
+ '.ico': 'image/x-icon',
54
+ };
55
+ /** 支持的文件扩展名列表 */
56
+ export const SUPPORTED_EXTENSIONS = Object.keys(EXT_TO_CATEGORY);
57
+ /** 图片扩展名列表 */
58
+ export const IMAGE_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg', '.bmp', '.ico'];
59
+ /** 文档扩展名列表(支持预览的) */
60
+ export const PREVIEWABLE_EXTENSIONS = ['.md', '.markdown', '.pdf', '.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg', '.bmp', '.ico'];
61
+ /** 可转换为 PDF 的扩展名 */
62
+ export const CONVERTIBLE_TO_PDF = ['.pptx', '.ppt'];
63
+ /**
64
+ * 获取文件分类
65
+ * @param filename - 文件名
66
+ * @returns 文件分类
67
+ */
68
+ export function getFileCategory(filename) {
69
+ const ext = filename.toLowerCase().slice(filename.lastIndexOf('.'));
70
+ return EXT_TO_CATEGORY[ext] ?? 'all';
71
+ }
72
+ /**
73
+ * 获取文件 MIME 类型
74
+ * @param filename - 文件名
75
+ * @returns MIME 类型
76
+ */
77
+ export function getFileMimeType(filename) {
78
+ const ext = filename.toLowerCase().slice(filename.lastIndexOf('.'));
79
+ return FILE_MIME_TYPES[ext] ?? 'application/octet-stream';
80
+ }
81
+ /**
82
+ * 检查文件是否可预览
83
+ * @param filename - 文件名
84
+ * @returns 是否可预览
85
+ */
86
+ export function isPreviewable(filename) {
87
+ const ext = filename.toLowerCase().slice(filename.lastIndexOf('.'));
88
+ return PREVIEWABLE_EXTENSIONS.includes(ext);
89
+ }
90
+ /**
91
+ * 检查文件是否可转换为 PDF
92
+ * @param filename - 文件名
93
+ * @returns 是否可转换
94
+ */
95
+ export function isConvertibleToPdf(filename) {
96
+ const ext = filename.toLowerCase().slice(filename.lastIndexOf('.'));
97
+ return CONVERTIBLE_TO_PDF.includes(ext);
98
+ }
99
+ /**
100
+ * 检查文件是否为图片
101
+ * @param filename - 文件名
102
+ * @returns 是否为图片
103
+ */
104
+ export function isImage(filename) {
105
+ const ext = filename.toLowerCase().slice(filename.lastIndexOf('.'));
106
+ return IMAGE_EXTENSIONS.includes(ext);
107
+ }
108
+ //# sourceMappingURL=file-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-types.js","sourceRoot":"","sources":["../../shared/file-types.ts"],"names":[],"mappings":"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"}
@@ -3,4 +3,5 @@ export * from './constants.js';
3
3
  export * from './instance.js';
4
4
  export * from './defaults.js';
5
5
  export * from './notification-types.js';
6
+ export * from './file-types.js';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../shared/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../shared/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC"}
@@ -3,4 +3,5 @@ export * from './constants.js';
3
3
  export * from './instance.js';
4
4
  export * from './defaults.js';
5
5
  export * from './notification-types.js';
6
+ export * from './file-types.js';
6
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../shared/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../shared/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC"}
@@ -11,6 +11,8 @@ export interface InstanceInfo {
11
11
  clientCount?: number;
12
12
  /** 创建时的 Claude 参数(可选,包含 --settings 等) */
13
13
  claudeArgs?: string[];
14
+ /** 使用的 CLI 命令(claude 或 cfuse) */
15
+ claudeCommand?: string;
14
16
  }
15
17
  export interface InstanceListItem extends InstanceInfo {
16
18
  isCurrent: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../../shared/instance.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iBAAiB;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,gBAAiB,SAAQ,YAAY;IACpD,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,2BAA2B;AAC3B,eAAO,MAAM,iBAAiB,mBAAmB,CAAC;AAElD,+BAA+B;AAC/B,eAAO,MAAM,YAAY,aAAa,CAAC;AAEvC,oBAAoB;AACpB,MAAM,WAAW,YAAY;IAC3B,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB;IAChB,aAAa,EAAE,MAAM,CAAC;CACvB"}
1
+ {"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../../shared/instance.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iBAAiB;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,iCAAiC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAiB,SAAQ,YAAY;IACpD,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,2BAA2B;AAC3B,eAAO,MAAM,iBAAiB,mBAAmB,CAAC;AAElD,+BAA+B;AAC/B,eAAO,MAAM,YAAY,aAAa,CAAC;AAEvC,oBAAoB;AACpB,MAAM,WAAW,YAAY;IAC3B,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB;IAChB,aAAa,EAAE,MAAM,CAAC;CACvB"}
@@ -1 +1 @@
1
- {"version":3,"file":"instance.js","sourceRoot":"","sources":["../../shared/instance.ts"],"names":[],"mappings":"AAmBA,2BAA2B;AAC3B,MAAM,CAAC,MAAM,iBAAiB,GAAG,gBAAgB,CAAC;AAElD,+BAA+B;AAC/B,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC"}
1
+ {"version":3,"file":"instance.js","sourceRoot":"","sources":["../../shared/instance.ts"],"names":[],"mappings":"AAqBA,2BAA2B;AAC3B,MAAM,CAAC,MAAM,iBAAiB,GAAG,gBAAgB,CAAC;AAElD,+BAA+B;AAC/B,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC"}
@@ -38,4 +38,4 @@
38
38
 
39
39
  Outdated base version: https://github.com/primer/github-syntax-dark
40
40
  Current colors taken from GitHub's CSS
41
- */.hljs{color:#c9d1d9;background:#0d1117}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#ff7b72}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#d2a8ff}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#79c0ff}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#a5d6ff}.hljs-built_in,.hljs-symbol{color:#ffa657}.hljs-comment,.hljs-code,.hljs-formula{color:#8b949e}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#7ee787}.hljs-subst{color:#c9d1d9}.hljs-section{color:#1f6feb;font-weight:700}.hljs-bullet{color:#f2cc60}.hljs-emphasis{color:#c9d1d9;font-style:italic}.hljs-strong{color:#c9d1d9;font-weight:700}.hljs-addition{color:#aff5b4;background-color:#033a16}.hljs-deletion{color:#ffdcd7;background-color:#67060c}.markdown-body{-webkit-overflow-scrolling:touch}.markdown-body pre{overflow-x:auto;max-width:100%}.markdown-body table{display:block;overflow-x:auto;max-width:100%}@media(max-width:768px){.toc-fab{display:flex!important}.toc-drawer{display:block!important}.toc-sidebar{display:none!important}}@media(min-width:769px){.toc-fab,.toc-drawer{display:none!important}.toc-sidebar{display:block!important}.viewer-content{margin-right:260px}}.markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Noto Sans,Helvetica,Arial,sans-serif;font-size:1rem;line-height:1.6;color:var(--text-primary);word-wrap:break-word}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:1.5em;margin-bottom:.5em;font-weight:600;line-height:1.25;scroll-margin-top:4rem;text-wrap:pretty}.markdown-body h1{font-size:1.75rem;padding-bottom:.3em;border-bottom:1px solid var(--border-color)}.markdown-body h2{font-size:1.5rem;padding-bottom:.3em;border-bottom:1px solid var(--border-color)}.markdown-body h3{font-size:1.25rem}.markdown-body h4{font-size:1rem}.markdown-body h5{font-size:.875rem}.markdown-body h6{font-size:.85em;color:var(--text-secondary)}.markdown-body p{margin:1em 0}.markdown-body a{color:var(--accent-color);text-decoration:none;min-height:44px;display:inline-flex;align-items:center}.markdown-body a:hover{text-decoration:underline}.markdown-body ul,.markdown-body ol{margin:1em 0;padding-left:2em}.markdown-body li{margin:.25em 0}.markdown-body li+li{margin-top:.25em}.markdown-body blockquote{margin:1em 0;padding:1em 1.25em;border-left:4px solid var(--accent-color);background:var(--bg-secondary);color:var(--text-secondary);border-radius:0 .5rem .5rem 0}.markdown-body blockquote p{margin:0}.markdown-body blockquote p+p{margin-top:.5em}.markdown-body code{padding:.2em .4em;background:var(--bg-secondary);border-radius:.25rem;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,monospace;font-size:.875em}.markdown-body pre{margin:1em 0;padding:1em;background:var(--bg-secondary);border-radius:.5rem;overflow-x:auto;-webkit-overflow-scrolling:touch}.markdown-body pre code{padding:0;background:none;font-size:.875rem;line-height:1.45}.markdown-body table{margin:1em 0;border-collapse:collapse;width:100%;overflow:auto;display:block;-webkit-overflow-scrolling:touch}.markdown-body table th,.markdown-body table td{padding:.5em .75em;border:1px solid var(--border-color)}.markdown-body table th{font-weight:600;background:var(--bg-secondary)}.markdown-body table tr:nth-child(2n){background:var(--bg-secondary)}.hljs{background:transparent!important;padding:0!important}.markdown-body input[type=checkbox]{margin-right:.5em;vertical-align:middle;width:18px;height:18px;min-width:18px;min-height:18px;cursor:pointer}.markdown-body img{max-width:100%;height:auto;border-radius:.5rem;box-shadow:0 2px 8px #0000001a;transition:opacity .2s ease,box-shadow .2s ease}.markdown-body img:hover{box-shadow:0 4px 16px #00000026}.markdown-body img[src=""]{display:none}.markdown-body hr{margin:2em 0;border:none;border-top:1px solid var(--border-color)}.markdown-body del{color:var(--text-secondary)}@media(max-width:768px){.markdown-body{font-size:16px;line-height:1.75}.markdown-body p{margin:1.25em 0}.markdown-body h1{font-size:1.5rem}.markdown-body h2{font-size:1.375rem}.markdown-body h3{font-size:1.125rem}.markdown-body ul,.markdown-body ol{padding-left:1.5em}.markdown-body pre{padding:.875em;font-size:.8125rem}.markdown-body code{font-size:.8125em}.markdown-body blockquote{padding:.875em 1em}.markdown-body table{font-size:.875rem}.markdown-body table th,.markdown-body table td{padding:.375em .5em}}@media(prefers-reduced-motion:reduce){.markdown-body img,.markdown-body a,.markdown-body *{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}.image-preview-trigger{cursor:pointer}@supports (padding-top: env(safe-area-inset-top)){.markdown-body{padding-left:env(safe-area-inset-left);padding-right:env(safe-area-inset-right)}}.markdown-body span[style*="color:"],.markdown-body font[color]{display:inline}.markdown-body sub,.markdown-body sup{font-size:.75em;line-height:0;position:relative;vertical-align:baseline}.markdown-body sup{top:-.5em}.markdown-body sub{bottom:-.25em}.markdown-body mark{background-color:#ffd7004d;padding:.125em .25em;border-radius:.125rem}.markdown-body br{display:block;content:"";margin-top:.5em}:root{color-scheme:dark;--bg-primary: #0d1117;--bg-secondary: #161b22;--bg-tertiary: #21262d;--bg-overlay: rgba(0, 0, 0, .6);--text-primary: #e6edf3;--text-secondary: #8b949e;--text-muted: #484f58;--border-color: #30363d;--status-idle: #3fb950;--status-running: #58a6ff;--status-waiting: #d29922;--status-error: #f85149;--status-disconnected: #8b949e;--approve-bg: #238636;--approve-hover: #2ea043;--reject-bg: #da3633;--reject-hover: #f85149;--safe-top: env(safe-area-inset-top, 0px);--safe-bottom: env(safe-area-inset-bottom, 0px);--safe-left: env(safe-area-inset-left, 0px);--safe-right: env(safe-area-inset-right, 0px);--statusbar-height: 44px;--inputbar-height: 56px;--min-touch-target: 44px;--keybar-height: 48px;--breakpoint-tablet: 768px;--breakpoint-desktop: 1024px;--app-height: 100dvh;--content-inline-padding: 12px;--content-inline-padding-tablet: 16px;--bottom-interactive-inset: var(--safe-bottom);--font-mono: "JetBrains Mono", "Menlo", "Monaco", "Courier New", monospace;--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html,body,#root{height:var(--app-height);width:100%;overflow:hidden;background:var(--bg-primary);color:var(--text-primary);font-family:var(--font-sans);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;overscroll-behavior:none}@supports not (height: 100dvh){:root{--app-height: 100vh}}body{padding-left:var(--safe-left);padding-right:var(--safe-right)}@media(min-width:768px){:root{--content-inline-padding: var(--content-inline-padding-tablet)}}button,input,label,nav{-webkit-user-select:none;user-select:none}input{font-family:inherit;font-size:16px}button{cursor:pointer;border:none;background:none;font-family:inherit;font-size:inherit;color:inherit}.app-toast{position:fixed;left:50%;bottom:calc(16px + var(--safe-bottom));transform:translate(-50%);z-index:2000;padding:8px 12px;border-radius:8px;background:#111827eb;color:#fff;font-size:13px;line-height:1.4;white-space:nowrap}.app-toast-top{top:calc(var(--safe-top) + 8px);bottom:auto}.focus-ring:focus-visible{outline:none;box-shadow:0 0 0 2px var(--bg-primary),0 0 0 4px #58a6ff}.perm-btn{touch-action:manipulation;-webkit-tap-highlight-color:transparent;transition:opacity .1s,background .1s}.perm-btn:hover{opacity:.85}.perm-btn:active{opacity:.7}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}input:focus-visible,textarea:focus-visible{outline:none;box-shadow:0 0 0 2px var(--bg-primary),0 0 0 4px #58a6ff}button{touch-action:manipulation;-webkit-tap-highlight-color:transparent}.xterm-helper-textarea{pointer-events:none;-webkit-user-select:none;user-select:none}.xterm{height:100%;width:100%}@keyframes fadeInOut{0%{opacity:0;transform:translate(-50%) translateY(10px)}10%{opacity:1;transform:translate(-50%) translateY(0)}90%{opacity:1;transform:translate(-50%) translateY(0)}to{opacity:0;transform:translate(-50%) translateY(-10px)}}
41
+ */.hljs{color:#c9d1d9;background:#0d1117}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#ff7b72}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#d2a8ff}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#79c0ff}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#a5d6ff}.hljs-built_in,.hljs-symbol{color:#ffa657}.hljs-comment,.hljs-code,.hljs-formula{color:#8b949e}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#7ee787}.hljs-subst{color:#c9d1d9}.hljs-section{color:#1f6feb;font-weight:700}.hljs-bullet{color:#f2cc60}.hljs-emphasis{color:#c9d1d9;font-style:italic}.hljs-strong{color:#c9d1d9;font-weight:700}.hljs-addition{color:#aff5b4;background-color:#033a16}.hljs-deletion{color:#ffdcd7;background-color:#67060c}.markdown-body{-webkit-overflow-scrolling:touch}.markdown-body pre{overflow-x:auto;max-width:100%}.markdown-body table{display:block;overflow-x:auto;max-width:100%}@media(max-width:768px){.toc-fab{display:flex!important}.toc-drawer{display:block!important}.toc-sidebar{display:none!important}}@media(min-width:769px){.toc-fab,.toc-drawer{display:none!important}.toc-sidebar{display:block!important}.viewer-content{margin-right:260px}}.markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Noto Sans,Helvetica,Arial,sans-serif;font-size:1rem;line-height:1.6;color:var(--text-primary);word-wrap:break-word}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:1.5em;margin-bottom:.5em;font-weight:600;line-height:1.25;scroll-margin-top:4rem;text-wrap:pretty}.markdown-body h1{font-size:1.75rem;padding-bottom:.3em;border-bottom:1px solid var(--border-color)}.markdown-body h2{font-size:1.5rem;padding-bottom:.3em;border-bottom:1px solid var(--border-color)}.markdown-body h3{font-size:1.25rem}.markdown-body h4{font-size:1rem}.markdown-body h5{font-size:.875rem}.markdown-body h6{font-size:.85em;color:var(--text-secondary)}.markdown-body p{margin:1em 0}.markdown-body a{color:var(--accent-color);text-decoration:none;min-height:44px;display:inline-flex;align-items:center}.markdown-body a:hover{text-decoration:underline}.markdown-body ul,.markdown-body ol{margin:1em 0;padding-left:2em}.markdown-body li{margin:.25em 0}.markdown-body li+li{margin-top:.25em}.markdown-body blockquote{margin:1em 0;padding:1em 1.25em;border-left:4px solid var(--accent-color);background:var(--bg-secondary);color:var(--text-secondary);border-radius:0 .5rem .5rem 0}.markdown-body blockquote p{margin:0}.markdown-body blockquote p+p{margin-top:.5em}.markdown-body code{padding:.2em .4em;background:var(--bg-secondary);border-radius:.25rem;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,monospace;font-size:.875em}.markdown-body pre{margin:1em 0;padding:1em;background:var(--bg-secondary);border-radius:.5rem;overflow-x:auto;-webkit-overflow-scrolling:touch}.markdown-body pre code{padding:0;background:none;font-size:.875rem;line-height:1.45}.markdown-body table{margin:1em 0;border-collapse:collapse;width:100%;overflow:auto;display:block;-webkit-overflow-scrolling:touch}.markdown-body table th,.markdown-body table td{padding:.5em .75em;border:1px solid var(--border-color)}.markdown-body table th{font-weight:600;background:var(--bg-secondary)}.markdown-body table tr:nth-child(2n){background:var(--bg-secondary)}.hljs{background:transparent!important;padding:0!important}.markdown-body input[type=checkbox]{margin-right:.5em;vertical-align:middle;width:18px;height:18px;min-width:18px;min-height:18px;cursor:pointer}.markdown-body img{max-width:100%;height:auto;border-radius:.5rem;box-shadow:0 2px 8px #0000001a;transition:opacity .2s ease,box-shadow .2s ease}.markdown-body img:hover{box-shadow:0 4px 16px #00000026}.markdown-body img[src=""]{display:none}.markdown-body hr{margin:2em 0;border:none;border-top:1px solid var(--border-color)}.markdown-body del{color:var(--text-secondary)}@media(max-width:768px){.markdown-body{font-size:16px;line-height:1.75}.markdown-body p{margin:1.25em 0}.markdown-body h1{font-size:1.5rem}.markdown-body h2{font-size:1.375rem}.markdown-body h3{font-size:1.125rem}.markdown-body ul,.markdown-body ol{padding-left:1.5em}.markdown-body pre{padding:.875em;font-size:.8125rem}.markdown-body code{font-size:.8125em}.markdown-body blockquote{padding:.875em 1em}.markdown-body table{font-size:.875rem}.markdown-body table th,.markdown-body table td{padding:.375em .5em}}@media(prefers-reduced-motion:reduce){.markdown-body img,.markdown-body a,.markdown-body *{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}.image-preview-trigger{cursor:pointer}@supports (padding-top: env(safe-area-inset-top)){.markdown-body{padding-left:env(safe-area-inset-left);padding-right:env(safe-area-inset-right)}}.markdown-body span[style*="color:"],.markdown-body font[color]{display:inline}.markdown-body sub,.markdown-body sup{font-size:.75em;line-height:0;position:relative;vertical-align:baseline}.markdown-body sup{top:-.5em}.markdown-body sub{bottom:-.25em}.markdown-body mark{background-color:#ffd7004d;padding:.125em .25em;border-radius:.125rem}.markdown-body br{display:block;content:"";margin-top:.5em}:root{color-scheme:dark;--bg-primary: #0d1117;--bg-secondary: #161b22;--bg-tertiary: #21262d;--bg-overlay: rgba(0, 0, 0, .6);--text-primary: #e6edf3;--text-secondary: #8b949e;--text-muted: #484f58;--border-color: #30363d;--status-idle: #3fb950;--status-running: #58a6ff;--status-waiting: #d29922;--status-error: #f85149;--status-disconnected: #8b949e;--approve-bg: #238636;--approve-hover: #2ea043;--reject-bg: #da3633;--reject-hover: #f85149;--safe-top: env(safe-area-inset-top, 0px);--safe-bottom: env(safe-area-inset-bottom, 0px);--safe-left: env(safe-area-inset-left, 0px);--safe-right: env(safe-area-inset-right, 0px);--statusbar-height: 44px;--inputbar-height: 56px;--min-touch-target: 44px;--keybar-height: 48px;--breakpoint-tablet: 768px;--breakpoint-desktop: 1024px;--app-height: 100dvh;--content-inline-padding: 12px;--content-inline-padding-tablet: 16px;--bottom-interactive-inset: var(--safe-bottom);--font-mono: "JetBrains Mono", "Menlo", "Monaco", "Courier New", monospace;--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html,body,#root{height:var(--app-height);width:100%;overflow:hidden;background:var(--bg-primary);color:var(--text-primary);font-family:var(--font-sans);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;overscroll-behavior:none}@supports not (height: 100dvh){:root{--app-height: 100vh}}body{padding-left:var(--safe-left);padding-right:var(--safe-right)}@media(min-width:768px){:root{--content-inline-padding: var(--content-inline-padding-tablet)}}button,input,label,nav{-webkit-user-select:none;user-select:none}input{font-family:inherit;font-size:16px}button{cursor:pointer;border:none;background:none;font-family:inherit;font-size:inherit;color:inherit}.app-toast{position:fixed;left:50%;bottom:calc(16px + var(--safe-bottom));transform:translate(-50%);z-index:2000;padding:8px 12px;border-radius:8px;background:#111827eb;color:#fff;font-size:13px;line-height:1.4;white-space:nowrap}.app-toast-top{top:calc(var(--safe-top) + 8px);bottom:auto}.focus-ring:focus-visible{outline:none;box-shadow:0 0 0 2px var(--bg-primary),0 0 0 4px #58a6ff}.perm-btn{touch-action:manipulation;-webkit-tap-highlight-color:transparent;transition:opacity .1s,background .1s}.perm-btn:hover{opacity:.85}.perm-btn:active{opacity:.7}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}input:focus-visible,textarea:focus-visible{outline:none;box-shadow:0 0 0 2px var(--bg-primary),0 0 0 4px #58a6ff}button{touch-action:manipulation;-webkit-tap-highlight-color:transparent}.xterm-helper-textarea{pointer-events:none;-webkit-user-select:none;user-select:none}.xterm{height:100%;width:100%}@keyframes fadeInOut{0%{opacity:0;transform:translate(-50%) translateY(10px)}10%{opacity:1;transform:translate(-50%) translateY(0)}90%{opacity:1;transform:translate(-50%) translateY(0)}to{opacity:0;transform:translate(-50%) translateY(-10px)}}@keyframes fileSelectorSlideIn{0%{transform:translateY(100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes fileSelectorSlideOut{0%{transform:translateY(0);opacity:1}to{transform:translateY(100%);opacity:0}}@keyframes spin{to{transform:rotate(360deg)}}