hammoc 1.2.3 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -9
- package/package.json +5 -2
- package/packages/client/dist/assets/{index-B2I3yEWl.js → index-6jREnVYd.js} +1 -1
- package/packages/client/dist/assets/index-BFF0iqyW.css +32 -0
- package/packages/client/dist/assets/index-BcI4y-fU.js +1454 -0
- package/packages/client/dist/index.html +2 -2
- package/packages/client/dist/sw.js +1 -1
- package/packages/server/dist/app.d.ts.map +1 -1
- package/packages/server/dist/app.js +11 -3
- package/packages/server/dist/app.js.map +1 -1
- package/packages/server/dist/controllers/boardController.d.ts.map +1 -1
- package/packages/server/dist/controllers/boardController.js +0 -5
- package/packages/server/dist/controllers/boardController.js.map +1 -1
- package/packages/server/dist/controllers/fileSystemController.d.ts +4 -0
- package/packages/server/dist/controllers/fileSystemController.d.ts.map +1 -1
- package/packages/server/dist/controllers/fileSystemController.js +20 -2
- package/packages/server/dist/controllers/fileSystemController.js.map +1 -1
- package/packages/server/dist/controllers/projectController.js +1 -1
- package/packages/server/dist/controllers/projectController.js.map +1 -1
- package/packages/server/dist/controllers/queueTemplateController.js +2 -2
- package/packages/server/dist/controllers/queueTemplateController.js.map +1 -1
- package/packages/server/dist/controllers/serverController.d.ts.map +1 -1
- package/packages/server/dist/controllers/serverController.js +86 -50
- package/packages/server/dist/controllers/serverController.js.map +1 -1
- package/packages/server/dist/handlers/websocket.d.ts +1 -0
- package/packages/server/dist/handlers/websocket.d.ts.map +1 -1
- package/packages/server/dist/handlers/websocket.js +241 -49
- package/packages/server/dist/handlers/websocket.js.map +1 -1
- package/packages/server/dist/index.js +61 -0
- package/packages/server/dist/index.js.map +1 -1
- package/packages/server/dist/locales/en/server.json +9 -3
- package/packages/server/dist/locales/es/server.json +4 -2
- package/packages/server/dist/locales/ja/server.json +4 -2
- package/packages/server/dist/locales/ko/server.json +9 -3
- package/packages/server/dist/locales/pt/server.json +4 -2
- package/packages/server/dist/locales/zh-CN/server.json +4 -2
- package/packages/server/dist/routes/account.d.ts +7 -0
- package/packages/server/dist/routes/account.d.ts.map +1 -0
- package/packages/server/dist/routes/account.js +35 -0
- package/packages/server/dist/routes/account.js.map +1 -0
- package/packages/server/dist/routes/debug.d.ts +1 -1
- package/packages/server/dist/routes/debug.d.ts.map +1 -1
- package/packages/server/dist/routes/debug.js +60 -1
- package/packages/server/dist/routes/debug.js.map +1 -1
- package/packages/server/dist/routes/preferences.d.ts.map +1 -1
- package/packages/server/dist/routes/preferences.js +11 -2
- package/packages/server/dist/routes/preferences.js.map +1 -1
- package/packages/server/dist/services/accountInfoService.d.ts +38 -0
- package/packages/server/dist/services/accountInfoService.d.ts.map +1 -0
- package/packages/server/dist/services/accountInfoService.js +118 -0
- package/packages/server/dist/services/accountInfoService.js.map +1 -0
- package/packages/server/dist/services/chatService.d.ts.map +1 -1
- package/packages/server/dist/services/chatService.js +27 -2
- package/packages/server/dist/services/chatService.js.map +1 -1
- package/packages/server/dist/services/fileSystemService.d.ts +7 -1
- package/packages/server/dist/services/fileSystemService.d.ts.map +1 -1
- package/packages/server/dist/services/fileSystemService.js +67 -8
- package/packages/server/dist/services/fileSystemService.js.map +1 -1
- package/packages/server/dist/services/fileWatcherService.d.ts +35 -0
- package/packages/server/dist/services/fileWatcherService.d.ts.map +1 -0
- package/packages/server/dist/services/fileWatcherService.js +138 -0
- package/packages/server/dist/services/fileWatcherService.js.map +1 -0
- package/packages/server/dist/services/gitService.d.ts.map +1 -1
- package/packages/server/dist/services/gitService.js +67 -7
- package/packages/server/dist/services/gitService.js.map +1 -1
- package/packages/server/dist/services/historyParser.d.ts +4 -14
- package/packages/server/dist/services/historyParser.d.ts.map +1 -1
- package/packages/server/dist/services/historyParser.js +60 -5
- package/packages/server/dist/services/historyParser.js.map +1 -1
- package/packages/server/dist/services/issueService.d.ts.map +1 -1
- package/packages/server/dist/services/issueService.js +10 -3
- package/packages/server/dist/services/issueService.js.map +1 -1
- package/packages/server/dist/services/notificationService.d.ts.map +1 -1
- package/packages/server/dist/services/notificationService.js +34 -9
- package/packages/server/dist/services/notificationService.js.map +1 -1
- package/packages/server/dist/services/preferencesService.d.ts.map +1 -1
- package/packages/server/dist/services/preferencesService.js +8 -1
- package/packages/server/dist/services/preferencesService.js.map +1 -1
- package/packages/server/dist/services/projectService.d.ts +5 -0
- package/packages/server/dist/services/projectService.d.ts.map +1 -1
- package/packages/server/dist/services/projectService.js +42 -2
- package/packages/server/dist/services/projectService.js.map +1 -1
- package/packages/server/dist/services/ptyService.d.ts +1 -0
- package/packages/server/dist/services/ptyService.d.ts.map +1 -1
- package/packages/server/dist/services/ptyService.js +36 -5
- package/packages/server/dist/services/ptyService.js.map +1 -1
- package/packages/server/dist/services/queueService.d.ts +17 -0
- package/packages/server/dist/services/queueService.d.ts.map +1 -1
- package/packages/server/dist/services/queueService.js +215 -25
- package/packages/server/dist/services/queueService.js.map +1 -1
- package/packages/server/dist/services/sessionBufferManager.d.ts.map +1 -1
- package/packages/server/dist/services/sessionBufferManager.js +26 -0
- package/packages/server/dist/services/sessionBufferManager.js.map +1 -1
- package/packages/server/dist/services/sessionService.d.ts +15 -3
- package/packages/server/dist/services/sessionService.d.ts.map +1 -1
- package/packages/server/dist/services/sessionService.js +64 -6
- package/packages/server/dist/services/sessionService.js.map +1 -1
- package/packages/server/dist/services/streamHandler.d.ts.map +1 -1
- package/packages/server/dist/services/streamHandler.js +2 -1
- package/packages/server/dist/services/streamHandler.js.map +1 -1
- package/packages/server/dist/services/webPushService.d.ts.map +1 -1
- package/packages/server/dist/services/webPushService.js +8 -1
- package/packages/server/dist/services/webPushService.js.map +1 -1
- package/packages/server/dist/snippets/brownfield-create-story +3 -2
- package/packages/server/dist/utils/effortUtils.d.ts +21 -0
- package/packages/server/dist/utils/effortUtils.d.ts.map +1 -0
- package/packages/server/dist/utils/effortUtils.js +36 -0
- package/packages/server/dist/utils/effortUtils.js.map +1 -0
- package/packages/server/dist/utils/errors.d.ts +1 -0
- package/packages/server/dist/utils/errors.d.ts.map +1 -1
- package/packages/server/dist/utils/errors.js +12 -0
- package/packages/server/dist/utils/errors.js.map +1 -1
- package/packages/server/dist/utils/pathUtils.d.ts +3 -2
- package/packages/server/dist/utils/pathUtils.d.ts.map +1 -1
- package/packages/server/dist/utils/pathUtils.js +26 -2
- package/packages/server/dist/utils/pathUtils.js.map +1 -1
- package/packages/server/package.json +2 -1
- package/packages/shared/dist/types/fileSystem.d.ts +19 -0
- package/packages/shared/dist/types/fileSystem.d.ts.map +1 -1
- package/packages/shared/dist/types/fileSystem.js +5 -0
- package/packages/shared/dist/types/fileSystem.js.map +1 -1
- package/packages/shared/dist/types/git.d.ts +6 -1
- package/packages/shared/dist/types/git.d.ts.map +1 -1
- package/packages/shared/dist/types/git.js.map +1 -1
- package/packages/shared/dist/types/history.d.ts +7 -0
- package/packages/shared/dist/types/history.d.ts.map +1 -1
- package/packages/shared/dist/types/preferences.d.ts +2 -1
- package/packages/shared/dist/types/preferences.d.ts.map +1 -1
- package/packages/shared/dist/types/preferences.js +1 -0
- package/packages/shared/dist/types/preferences.js.map +1 -1
- package/packages/shared/dist/types/queue.d.ts +23 -1
- package/packages/shared/dist/types/queue.d.ts.map +1 -1
- package/packages/shared/dist/types/sdk.d.ts +47 -1
- package/packages/shared/dist/types/sdk.d.ts.map +1 -1
- package/packages/shared/dist/types/sdk.js +39 -0
- package/packages/shared/dist/types/sdk.js.map +1 -1
- package/packages/shared/dist/types/websocket.d.ts +14 -0
- package/packages/shared/dist/types/websocket.d.ts.map +1 -1
- package/packages/shared/dist/utils/queueParser.d.ts.map +1 -1
- package/packages/shared/dist/utils/queueParser.js +197 -12
- package/packages/shared/dist/utils/queueParser.js.map +1 -1
- package/scripts/mock-telegram.mjs +172 -0
- package/scripts/run-integration-test.mjs +362 -0
- package/packages/client/dist/assets/index-BghgIdOq.js +0 -1421
- package/packages/client/dist/assets/index-Cc_AX5QV.css +0 -32
|
@@ -112,6 +112,7 @@
|
|
|
112
112
|
"slugRequired": "El identificador del proyecto es obligatorio.",
|
|
113
113
|
"pathRequired": "El parámetro de consulta path es obligatorio",
|
|
114
114
|
"contentRequired": "content debe ser una cadena en el cuerpo de la solicitud",
|
|
115
|
+
"expectedMtimeType": "expectedMtime debe ser una cadena.",
|
|
115
116
|
"typeRequired": "type debe ser \"file\" o \"directory\"",
|
|
116
117
|
"newPathRequired": "El parámetro de consulta newPath es obligatorio",
|
|
117
118
|
"queryRequired": "El parámetro query es obligatorio"
|
|
@@ -126,7 +127,8 @@
|
|
|
126
127
|
"fileAlreadyExists": "El archivo ya existe.",
|
|
127
128
|
"protectedPath": "Ruta protegida.",
|
|
128
129
|
"renameTargetExists": "El destino del renombrado ya existe.",
|
|
129
|
-
"parentNotFound": "Directorio padre no encontrado."
|
|
130
|
+
"parentNotFound": "Directorio padre no encontrado.",
|
|
131
|
+
"staleWrite": "El archivo cambió en el disco después de abrirlo. Recarga para ver los cambios o sobrescribe para conservar los tuyos."
|
|
130
132
|
}
|
|
131
133
|
},
|
|
132
134
|
"git": {
|
|
@@ -169,7 +171,7 @@
|
|
|
169
171
|
"alreadyRunning": "La cola ya está en ejecución para este proyecto",
|
|
170
172
|
"noRunningQueue": "No hay cola en ejecución para este proyecto",
|
|
171
173
|
"sdkError": "Error SDK: {{value}}",
|
|
172
|
-
"
|
|
174
|
+
"pausewordDetected": "Palabra de pausa \"{{value}}\" detectada en la respuesta",
|
|
173
175
|
"sessionNotFound": "Nombre de sesión \"{{value}}\" no encontrado",
|
|
174
176
|
"sessionBusy": "La sesión está transmitiendo actualmente — cola pausada para evitar conflictos"
|
|
175
177
|
},
|
|
@@ -112,6 +112,7 @@
|
|
|
112
112
|
"slugRequired": "プロジェクト識別子が必要です。",
|
|
113
113
|
"pathRequired": "pathクエリパラメータが必要です",
|
|
114
114
|
"contentRequired": "リクエストボディのcontentは文字列である必要があります",
|
|
115
|
+
"expectedMtimeType": "expectedMtimeは文字列である必要があります。",
|
|
115
116
|
"typeRequired": "typeは\"file\"または\"directory\"である必要があります",
|
|
116
117
|
"newPathRequired": "newPathクエリパラメータが必要です",
|
|
117
118
|
"queryRequired": "queryパラメータが必要です"
|
|
@@ -126,7 +127,8 @@
|
|
|
126
127
|
"fileAlreadyExists": "ファイルは既に存在します。",
|
|
127
128
|
"protectedPath": "保護されたパスです。",
|
|
128
129
|
"renameTargetExists": "リネーム先が既に存在します。",
|
|
129
|
-
"parentNotFound": "親ディレクトリが見つかりません。"
|
|
130
|
+
"parentNotFound": "親ディレクトリが見つかりません。",
|
|
131
|
+
"staleWrite": "ファイルを開いた後、ディスク上で変更されました。再読み込みするか、上書きしてください。"
|
|
130
132
|
}
|
|
131
133
|
},
|
|
132
134
|
"git": {
|
|
@@ -169,7 +171,7 @@
|
|
|
169
171
|
"alreadyRunning": "このプロジェクトのキューは既に実行中です",
|
|
170
172
|
"noRunningQueue": "このプロジェクトに実行中のキューはありません",
|
|
171
173
|
"sdkError": "SDKエラー: {{value}}",
|
|
172
|
-
"
|
|
174
|
+
"pausewordDetected": "レスポンスで停止キーワード \"{{value}}\" が検出されました",
|
|
173
175
|
"sessionNotFound": "セッション名 \"{{value}}\" が見つかりません",
|
|
174
176
|
"sessionBusy": "セッションは現在ストリーミング中です — 競合を防ぐためキューを一時停止しました"
|
|
175
177
|
},
|
|
@@ -112,6 +112,7 @@
|
|
|
112
112
|
"slugRequired": "프로젝트 식별자가 필요합니다.",
|
|
113
113
|
"pathRequired": "path 쿼리 파라미터가 필요합니다",
|
|
114
114
|
"contentRequired": "요청 본문에 content 문자열이 필요합니다",
|
|
115
|
+
"expectedMtimeType": "expectedMtime은 문자열이어야 합니다.",
|
|
115
116
|
"typeRequired": "type은 \"file\" 또는 \"directory\"이어야 합니다",
|
|
116
117
|
"newPathRequired": "newPath 쿼리 파라미터가 필요합니다",
|
|
117
118
|
"queryRequired": "query 파라미터가 필요합니다",
|
|
@@ -133,7 +134,8 @@
|
|
|
133
134
|
"uploadError": "파일 업로드 중 오류가 발생했습니다.",
|
|
134
135
|
"uploadLimitFileSize": "파일 크기가 10MB 제한을 초과합니다.",
|
|
135
136
|
"uploadLimitFileCount": "파일이 너무 많습니다 (최대 10개).",
|
|
136
|
-
"uploadLimitUnexpectedFile": "예상하지 못한 파일 필드입니다."
|
|
137
|
+
"uploadLimitUnexpectedFile": "예상하지 못한 파일 필드입니다.",
|
|
138
|
+
"staleWrite": "파일을 연 이후 디스크에서 변경되었습니다. 다시 불러오거나 덮어쓰기를 선택하세요."
|
|
137
139
|
}
|
|
138
140
|
},
|
|
139
141
|
"git": {
|
|
@@ -176,15 +178,19 @@
|
|
|
176
178
|
"alreadyRunning": "이 프로젝트에서 이미 큐가 실행 중입니다",
|
|
177
179
|
"noRunningQueue": "이 프로젝트에 실행 중인 큐가 없습니다",
|
|
178
180
|
"sdkError": "SDK 오류: {{value}}",
|
|
179
|
-
"
|
|
181
|
+
"pausewordDetected": "응답에서 정지 키워드 \"{{value}}\"이(가) 감지되었습니다",
|
|
180
182
|
"sessionNotFound": "세션 이름 \"{{value}}\"을(를) 찾을 수 없습니다",
|
|
181
183
|
"sessionBusy": "세션이 현재 스트리밍 중이므로 충돌 방지를 위해 큐가 일시정지되었습니다"
|
|
182
184
|
},
|
|
185
|
+
"loop": {
|
|
186
|
+
"maxExceeded": "루프 최대 반복 초과: {{max}}회 반복 후에도 \"{{until}}\" 토큰이 감지되지 않아 일시정지됨"
|
|
187
|
+
},
|
|
183
188
|
"pause": {
|
|
184
189
|
"userPaused": "사용자가 일시정지했습니다",
|
|
185
190
|
"waitingForPermission": "{{value}} 대기 중: {{toolName}}",
|
|
186
191
|
"userAnswer": "사용자 응답",
|
|
187
|
-
"permissionApproval": "권한 승인"
|
|
192
|
+
"permissionApproval": "권한 승인",
|
|
193
|
+
"pausewordDetected": "응답에서 정지 키워드 \"{{value}}\"이(가) 감지됨 — 확인을 위해 일시정지됨"
|
|
188
194
|
}
|
|
189
195
|
},
|
|
190
196
|
"queueTemplate": {
|
|
@@ -112,6 +112,7 @@
|
|
|
112
112
|
"slugRequired": "O identificador do projeto é obrigatório.",
|
|
113
113
|
"pathRequired": "O parâmetro de consulta path é obrigatório",
|
|
114
114
|
"contentRequired": "content deve ser uma string no corpo da requisição",
|
|
115
|
+
"expectedMtimeType": "expectedMtime deve ser uma string.",
|
|
115
116
|
"typeRequired": "type deve ser \"file\" ou \"directory\"",
|
|
116
117
|
"newPathRequired": "O parâmetro de consulta newPath é obrigatório",
|
|
117
118
|
"queryRequired": "O parâmetro query é obrigatório"
|
|
@@ -126,7 +127,8 @@
|
|
|
126
127
|
"fileAlreadyExists": "O arquivo já existe.",
|
|
127
128
|
"protectedPath": "Caminho protegido.",
|
|
128
129
|
"renameTargetExists": "O destino da renomeação já existe.",
|
|
129
|
-
"parentNotFound": "Diretório pai não encontrado."
|
|
130
|
+
"parentNotFound": "Diretório pai não encontrado.",
|
|
131
|
+
"staleWrite": "O ficheiro foi alterado no disco desde que o abriu. Recarregue para ver as alterações ou sobrescreva para manter as suas."
|
|
130
132
|
}
|
|
131
133
|
},
|
|
132
134
|
"git": {
|
|
@@ -169,7 +171,7 @@
|
|
|
169
171
|
"alreadyRunning": "A fila já está em execução para este projeto",
|
|
170
172
|
"noRunningQueue": "Não há fila em execução para este projeto",
|
|
171
173
|
"sdkError": "Erro SDK: {{value}}",
|
|
172
|
-
"
|
|
174
|
+
"pausewordDetected": "Palavra de pausa \"{{value}}\" detectada na resposta",
|
|
173
175
|
"sessionNotFound": "Nome de sessão \"{{value}}\" não encontrado",
|
|
174
176
|
"sessionBusy": "A sessão está transmitindo no momento — fila pausada para evitar conflitos"
|
|
175
177
|
},
|
|
@@ -112,6 +112,7 @@
|
|
|
112
112
|
"slugRequired": "请输入项目标识。",
|
|
113
113
|
"pathRequired": "path查询参数为必填项",
|
|
114
114
|
"contentRequired": "请求体中content必须为字符串",
|
|
115
|
+
"expectedMtimeType": "expectedMtime 必须为字符串。",
|
|
115
116
|
"typeRequired": "type必须为\"file\"或\"directory\"",
|
|
116
117
|
"newPathRequired": "newPath查询参数为必填项",
|
|
117
118
|
"queryRequired": "query参数为必填项"
|
|
@@ -126,7 +127,8 @@
|
|
|
126
127
|
"fileAlreadyExists": "文件已存在。",
|
|
127
128
|
"protectedPath": "受保护的路径。",
|
|
128
129
|
"renameTargetExists": "重命名目标已存在。",
|
|
129
|
-
"parentNotFound": "未找到父目录。"
|
|
130
|
+
"parentNotFound": "未找到父目录。",
|
|
131
|
+
"staleWrite": "打开文件后磁盘上的内容已被修改。请重新加载或覆盖保存。"
|
|
130
132
|
}
|
|
131
133
|
},
|
|
132
134
|
"git": {
|
|
@@ -169,7 +171,7 @@
|
|
|
169
171
|
"alreadyRunning": "该项目的队列已在运行中",
|
|
170
172
|
"noRunningQueue": "该项目没有正在运行的队列",
|
|
171
173
|
"sdkError": "SDK错误: {{value}}",
|
|
172
|
-
"
|
|
174
|
+
"pausewordDetected": "响应中检测到停止关键字 \"{{value}}\"",
|
|
173
175
|
"sessionNotFound": "未找到会话名称 \"{{value}}\"",
|
|
174
176
|
"sessionBusy": "会话正在流式传输中——队列已暂停以避免冲突"
|
|
175
177
|
},
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../../src/routes/account.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,QAAA,MAAM,MAAM,4CAAW,CAAC;AA+BxB,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Account Routes
|
|
3
|
+
* Claude Code account info (subscription type, API provider, email).
|
|
4
|
+
*/
|
|
5
|
+
import { Router } from 'express';
|
|
6
|
+
import { accountInfoService } from '../services/accountInfoService.js';
|
|
7
|
+
import { rateLimitProbeService } from '../services/rateLimitProbeService.js';
|
|
8
|
+
const router = Router();
|
|
9
|
+
// GET /api/account — return the in-memory account info (populated at startup)
|
|
10
|
+
router.get('/', (_req, res) => {
|
|
11
|
+
const { account, fetchedAt } = accountInfoService.getCached();
|
|
12
|
+
res.json({ account, fetchedAt });
|
|
13
|
+
});
|
|
14
|
+
// POST /api/account/refresh — force-fetch via a bootstrap query
|
|
15
|
+
router.post('/refresh', async (_req, res) => {
|
|
16
|
+
const account = await accountInfoService.refresh();
|
|
17
|
+
const { fetchedAt } = accountInfoService.getCached();
|
|
18
|
+
res.json({ account, fetchedAt });
|
|
19
|
+
});
|
|
20
|
+
// GET /api/account/usage — return subscription rate limit (5h/7d).
|
|
21
|
+
// Falls back to a fresh probe if cache is empty (e.g., WebSocket never connected).
|
|
22
|
+
router.get('/usage', async (_req, res) => {
|
|
23
|
+
let rateLimit = rateLimitProbeService.getCachedResult();
|
|
24
|
+
if (!rateLimit) {
|
|
25
|
+
rateLimit = await rateLimitProbeService.probe();
|
|
26
|
+
}
|
|
27
|
+
res.json({ rateLimit });
|
|
28
|
+
});
|
|
29
|
+
// POST /api/account/usage/refresh — force a fresh probe regardless of cache.
|
|
30
|
+
router.post('/usage/refresh', async (_req, res) => {
|
|
31
|
+
const rateLimit = await rateLimitProbeService.probe();
|
|
32
|
+
res.json({ rateLimit });
|
|
33
|
+
});
|
|
34
|
+
export default router;
|
|
35
|
+
//# sourceMappingURL=account.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account.js","sourceRoot":"","sources":["../../src/routes/account.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAG7E,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;AAExB,8EAA8E;AAC9E,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;IAC/C,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,kBAAkB,CAAC,SAAS,EAAE,CAAC;IAC9D,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,SAAS,EAAgC,CAAC,CAAC;AACjE,CAAC,CAAC,CAAC;AAEH,gEAAgE;AAChE,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,IAAa,EAAE,GAAa,EAAE,EAAE;IAC7D,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,OAAO,EAAE,CAAC;IACnD,MAAM,EAAE,SAAS,EAAE,GAAG,kBAAkB,CAAC,SAAS,EAAE,CAAC;IACrD,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,SAAS,EAAgC,CAAC,CAAC;AACjE,CAAC,CAAC,CAAC;AAEH,mEAAmE;AACnE,mFAAmF;AACnF,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAa,EAAE,GAAa,EAAE,EAAE;IAC1D,IAAI,SAAS,GAAiC,qBAAqB,CAAC,eAAe,EAAE,CAAC;IACtF,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,SAAS,GAAG,MAAM,qBAAqB,CAAC,KAAK,EAAE,CAAC;IAClD,CAAC;IACD,GAAG,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;AAC1B,CAAC,CAAC,CAAC;AAEH,6EAA6E;AAC7E,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,KAAK,EAAE,IAAa,EAAE,GAAa,EAAE,EAAE;IACnE,MAAM,SAAS,GAAG,MAAM,qBAAqB,CAAC,KAAK,EAAE,CAAC;IACtD,GAAG,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;AAC1B,CAAC,CAAC,CAAC;AAEH,eAAe,MAAM,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../src/routes/debug.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../src/routes/debug.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH,QAAA,MAAM,MAAM,4CAAW,CAAC;AAmHxB,eAAe,MAAM,CAAC"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Debug Routes - Server-side logging
|
|
2
|
+
* Debug Routes - Server-side logging and test helpers (dev only)
|
|
3
3
|
*/
|
|
4
4
|
import { Router } from 'express';
|
|
5
5
|
import { appendFileSync, mkdirSync, existsSync } from 'fs';
|
|
6
6
|
import path from 'path';
|
|
7
7
|
import { createLogger } from '../utils/logger.js';
|
|
8
|
+
import { getIO, setChainDrainFailureInjection } from '../handlers/websocket.js';
|
|
8
9
|
const log = createLogger('debugRoute');
|
|
9
10
|
const router = Router();
|
|
10
11
|
// Create logs directory if it doesn't exist
|
|
@@ -55,5 +56,63 @@ router.post('/log', (req, res) => {
|
|
|
55
56
|
res.status(500).json({ error: 'Failed to write log' });
|
|
56
57
|
}
|
|
57
58
|
});
|
|
59
|
+
/**
|
|
60
|
+
* POST /api/debug/kill-ws
|
|
61
|
+
* Forcibly disconnect WebSocket sockets for a session (dev test helper for R-01-01).
|
|
62
|
+
* Body: { sessionId?: string } — if omitted, disconnects all connected sockets.
|
|
63
|
+
*/
|
|
64
|
+
router.post('/kill-ws', async (req, res) => {
|
|
65
|
+
try {
|
|
66
|
+
const io = getIO();
|
|
67
|
+
const { sessionId } = req.body;
|
|
68
|
+
if (sessionId) {
|
|
69
|
+
const room = io.sockets.adapter.rooms.get(`session:${sessionId}`);
|
|
70
|
+
if (!room || room.size === 0) {
|
|
71
|
+
res.status(404).json({ error: 'No sockets found for sessionId', sessionId });
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
let count = 0;
|
|
75
|
+
for (const socketId of room) {
|
|
76
|
+
const sock = io.sockets.sockets.get(socketId);
|
|
77
|
+
if (sock) {
|
|
78
|
+
sock.disconnect(true);
|
|
79
|
+
count++;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
log.info(`kill-ws: disconnected ${count} socket(s) for session ${sessionId}`);
|
|
83
|
+
res.status(200).json({ success: true, disconnected: count, sessionId });
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
// Disconnect all connected sockets (no sessionId filter)
|
|
87
|
+
const sockets = await io.fetchSockets();
|
|
88
|
+
for (const sock of sockets) {
|
|
89
|
+
sock.disconnect(true);
|
|
90
|
+
}
|
|
91
|
+
log.info(`kill-ws: disconnected all ${sockets.length} socket(s)`);
|
|
92
|
+
res.status(200).json({ success: true, disconnected: sockets.length });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
log.error('kill-ws failed:', err);
|
|
97
|
+
res.status(500).json({ error: String(err) });
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
/**
|
|
101
|
+
* POST /api/debug/fail-next-chain-item
|
|
102
|
+
* Inject a synthetic failure into the next N chain drain attempts for a session
|
|
103
|
+
* (dev test helper for G-02-02 retry / failure-persistence scenarios).
|
|
104
|
+
* Body: { sessionId: string; count?: number } (count defaults to 1)
|
|
105
|
+
*/
|
|
106
|
+
router.post('/fail-next-chain-item', (req, res) => {
|
|
107
|
+
const { sessionId, count } = req.body;
|
|
108
|
+
if (!sessionId || typeof sessionId !== 'string') {
|
|
109
|
+
res.status(400).json({ error: 'sessionId is required' });
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const times = typeof count === 'number' && count > 0 ? Math.floor(count) : 1;
|
|
113
|
+
setChainDrainFailureInjection(sessionId, times);
|
|
114
|
+
log.info(`fail-next-chain-item: session=${sessionId} times=${times}`);
|
|
115
|
+
res.status(200).json({ success: true, sessionId, count: times });
|
|
116
|
+
});
|
|
58
117
|
export default router;
|
|
59
118
|
//# sourceMappingURL=debug.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debug.js","sourceRoot":"","sources":["../../src/routes/debug.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC3D,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"debug.js","sourceRoot":"","sources":["../../src/routes/debug.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preferences.d.ts","sourceRoot":"","sources":["../../src/routes/preferences.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,QAAA,MAAM,MAAM,4CAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"preferences.d.ts","sourceRoot":"","sources":["../../src/routes/preferences.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,QAAA,MAAM,MAAM,4CAAW,CAAC;AAmMxB,eAAe,MAAM,CAAC"}
|
|
@@ -24,8 +24,12 @@ router.get('/telegram', async (req, res) => {
|
|
|
24
24
|
// PATCH /api/preferences/telegram — Update Telegram settings
|
|
25
25
|
router.patch('/telegram', async (req, res) => {
|
|
26
26
|
try {
|
|
27
|
-
const { botToken, chatId, enabled, notifyPermission, notifyComplete, notifyError } = req.body;
|
|
28
|
-
const update = {
|
|
27
|
+
const { botToken, chatId, enabled, baseUrl, alwaysNotify, notifyPermission, notifyComplete, notifyError, notifyQueueStart, notifyQueueComplete, notifyQueueError, notifyQueueInputRequired, } = req.body;
|
|
28
|
+
const update = {
|
|
29
|
+
botToken, chatId, enabled, baseUrl, alwaysNotify,
|
|
30
|
+
notifyPermission, notifyComplete, notifyError,
|
|
31
|
+
notifyQueueStart, notifyQueueComplete, notifyQueueError, notifyQueueInputRequired,
|
|
32
|
+
};
|
|
29
33
|
if (update.botToken !== undefined && update.botToken !== null) {
|
|
30
34
|
if (typeof update.botToken !== 'string' || update.botToken.trim().length === 0) {
|
|
31
35
|
res.status(400).json({
|
|
@@ -180,6 +184,11 @@ router.patch('/', async (req, res) => {
|
|
|
180
184
|
if (req.body.language) {
|
|
181
185
|
invalidateI18nCache();
|
|
182
186
|
}
|
|
187
|
+
// Reload notification service when telegram/webPush settings change via the merge endpoint,
|
|
188
|
+
// so the in-memory service state matches the newly persisted file.
|
|
189
|
+
if (req.body.telegram !== undefined || req.body.webPush !== undefined) {
|
|
190
|
+
await notificationService.reload();
|
|
191
|
+
}
|
|
183
192
|
res.json(updated);
|
|
184
193
|
}
|
|
185
194
|
catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preferences.js","sourceRoot":"","sources":["../../src/routes/preferences.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAG5F,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;AAExB,iEAAiE;AACjE,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;IAC5D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,mBAAmB,EAAE,CAAC;QAChE,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,KAAK,EAAE,EAAE,IAAI,EAAE,8BAA8B,EAAE,OAAO,EAAE,GAAG,CAAC,CAAE,CAAC,gCAAgC,CAAC,EAAE;SACnG,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,6DAA6D;AAC7D,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;IAC9D,IAAI,CAAC;QACH,MAAM,
|
|
1
|
+
{"version":3,"file":"preferences.js","sourceRoot":"","sources":["../../src/routes/preferences.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Account Info Service
|
|
3
|
+
*
|
|
4
|
+
* Fetches Claude Code account information (subscription type, API provider,
|
|
5
|
+
* email) via the SDK control-initialize response.
|
|
6
|
+
*
|
|
7
|
+
* A lightweight bootstrap query (AsyncIterable prompt that never yields) is
|
|
8
|
+
* used to access the control interface without sending a real prompt; the
|
|
9
|
+
* query is aborted as soon as initializationResult returns.
|
|
10
|
+
*
|
|
11
|
+
* Kept in memory only — refreshed on server startup and on explicit user
|
|
12
|
+
* action. No disk persistence: a restart is cheaper than stale cache bugs.
|
|
13
|
+
*/
|
|
14
|
+
import type { AccountInfo } from '@hammoc/shared';
|
|
15
|
+
declare class AccountInfoService {
|
|
16
|
+
private memory;
|
|
17
|
+
private inflight;
|
|
18
|
+
getCached(): {
|
|
19
|
+
account: AccountInfo | null;
|
|
20
|
+
fetchedAt: number | null;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Run a bootstrap query on server startup (fire-and-forget, never throws).
|
|
24
|
+
*/
|
|
25
|
+
initOnStartup(): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Force-refresh via a short bootstrap query. Dedupes concurrent callers.
|
|
28
|
+
*/
|
|
29
|
+
refresh(): Promise<AccountInfo | null>;
|
|
30
|
+
/**
|
|
31
|
+
* Start a streaming-input query with an AsyncIterable that never yields,
|
|
32
|
+
* call initializationResult() to get the account, then abort.
|
|
33
|
+
*/
|
|
34
|
+
private bootstrapFetch;
|
|
35
|
+
}
|
|
36
|
+
export declare const accountInfoService: AccountInfoService;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=accountInfoService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accountInfoService.d.ts","sourceRoot":"","sources":["../../src/services/accountInfoService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAOlD,cAAM,kBAAkB;IACtB,OAAO,CAAC,MAAM,CAAmE;IACjF,OAAO,CAAC,QAAQ,CAA4C;IAE5D,SAAS,IAAI;QAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;IAOtE;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAcpC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAa5C;;;OAGG;YACW,cAAc;CAgD7B;AAED,eAAO,MAAM,kBAAkB,oBAA2B,CAAC"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Account Info Service
|
|
3
|
+
*
|
|
4
|
+
* Fetches Claude Code account information (subscription type, API provider,
|
|
5
|
+
* email) via the SDK control-initialize response.
|
|
6
|
+
*
|
|
7
|
+
* A lightweight bootstrap query (AsyncIterable prompt that never yields) is
|
|
8
|
+
* used to access the control interface without sending a real prompt; the
|
|
9
|
+
* query is aborted as soon as initializationResult returns.
|
|
10
|
+
*
|
|
11
|
+
* Kept in memory only — refreshed on server startup and on explicit user
|
|
12
|
+
* action. No disk persistence: a restart is cheaper than stale cache bugs.
|
|
13
|
+
*/
|
|
14
|
+
import os from 'node:os';
|
|
15
|
+
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
16
|
+
import { createLogger } from '../utils/logger.js';
|
|
17
|
+
const log = createLogger('accountInfoService');
|
|
18
|
+
const FETCH_TIMEOUT_MS = 15 * 1000;
|
|
19
|
+
class AccountInfoService {
|
|
20
|
+
memory = null;
|
|
21
|
+
inflight = null;
|
|
22
|
+
getCached() {
|
|
23
|
+
return {
|
|
24
|
+
account: this.memory?.account ?? null,
|
|
25
|
+
fetchedAt: this.memory?.fetchedAt ?? null,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Run a bootstrap query on server startup (fire-and-forget, never throws).
|
|
30
|
+
*/
|
|
31
|
+
async initOnStartup() {
|
|
32
|
+
try {
|
|
33
|
+
log.info('startup: fetching Claude Code account info...');
|
|
34
|
+
const account = await this.refresh();
|
|
35
|
+
if (account) {
|
|
36
|
+
log.info(`startup: account info fetched (subscription=${account.subscriptionType ?? 'unknown'}, provider=${account.apiProvider ?? 'unknown'})`);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
log.warn('startup: account info bootstrap returned null');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
log.warn(`startup refresh failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Force-refresh via a short bootstrap query. Dedupes concurrent callers.
|
|
48
|
+
*/
|
|
49
|
+
async refresh() {
|
|
50
|
+
if (this.inflight)
|
|
51
|
+
return this.inflight;
|
|
52
|
+
this.inflight = this.bootstrapFetch()
|
|
53
|
+
.then((account) => {
|
|
54
|
+
this.memory = { account, fetchedAt: Date.now() };
|
|
55
|
+
return account;
|
|
56
|
+
})
|
|
57
|
+
.finally(() => {
|
|
58
|
+
this.inflight = null;
|
|
59
|
+
});
|
|
60
|
+
return this.inflight;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Start a streaming-input query with an AsyncIterable that never yields,
|
|
64
|
+
* call initializationResult() to get the account, then abort.
|
|
65
|
+
*/
|
|
66
|
+
async bootstrapFetch() {
|
|
67
|
+
const controller = new AbortController();
|
|
68
|
+
const pendingPrompt = {
|
|
69
|
+
[Symbol.asyncIterator]() {
|
|
70
|
+
return {
|
|
71
|
+
next() {
|
|
72
|
+
return new Promise((_resolve, reject) => {
|
|
73
|
+
controller.signal.addEventListener('abort', () => {
|
|
74
|
+
reject(new Error('bootstrap aborted'));
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
const q = query({
|
|
82
|
+
prompt: pendingPrompt,
|
|
83
|
+
options: {
|
|
84
|
+
cwd: os.homedir(),
|
|
85
|
+
abortController: controller,
|
|
86
|
+
includePartialMessages: false,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
90
|
+
try {
|
|
91
|
+
const iter = q[Symbol.asyncIterator]();
|
|
92
|
+
const first = await iter.next();
|
|
93
|
+
if (first.done) {
|
|
94
|
+
log.warn('bootstrap query ended before init message');
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
const initResult = await q.initializationResult();
|
|
98
|
+
return initResult?.account ?? null;
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
log.warn(`bootstrap fetch failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
clearTimeout(timeout);
|
|
106
|
+
if (!controller.signal.aborted)
|
|
107
|
+
controller.abort();
|
|
108
|
+
try {
|
|
109
|
+
await q.return(undefined);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// ignore
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
export const accountInfoService = new AccountInfoService();
|
|
118
|
+
//# sourceMappingURL=accountInfoService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accountInfoService.js","sourceRoot":"","sources":["../../src/services/accountInfoService.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chatService.d.ts","sourceRoot":"","sources":["../../src/services/chatService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmC,KAAK,UAAU,EAAuB,KAAK,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACxI,OAAO,KAAK,EACV,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,cAAc,EACd,eAAe,EAEhB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"chatService.d.ts","sourceRoot":"","sources":["../../src/services/chatService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmC,KAAK,UAAU,EAAuB,KAAK,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACxI,OAAO,KAAK,EACV,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,cAAc,EACd,eAAe,EAEhB,MAAM,gBAAgB,CAAC;AAYxB;;;GAGG;AACH,eAAO,MAAM,0BAA0B,QAsB3B,CAAC;AAEb,0DAA0D;AAC1D,eAAO,MAAM,kBAAkB;;;;;;;;;EAIrB,CAAC;AAEX;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAsC9E;AASD;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,YAAY,CAAW;IAC/B,OAAO,CAAC,eAAe,CAAW;IAClC,OAAO,CAAC,YAAY,CAAsB;IAC1C,gFAAgF;IAChF,aAAa,EAAE,MAAM,GAAG,IAAI,CAAQ;gBAExB,MAAM,GAAE,iBAAsB;IAO1C;;OAEG;IACG,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWrD;;OAEG;YACW,mBAAmB;IASjC;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAItC;;OAEG;IACH,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAIzC;;OAEG;IACH,mBAAmB,IAAI,MAAM,GAAG,SAAS;IAIzC;;OAEG;IACI,WAAW,CAChB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,WAAgB,EACzB,UAAU,CAAC,EAAE,UAAU,GACtB,cAAc,CAAC,UAAU,EAAE,YAAY,EAAE,IAAI,CAAC;IAmLjD;;OAEG;IACG,eAAe,CACnB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,YAAY,CAAC;IAcxB;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAMhC;;OAEG;IACH,iBAAiB,IAAI,cAAc;IAInC;;OAEG;IACG,iBAAiB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAO5D;;;OAGG;IACG,wBAAwB,CAC5B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,eAAe,EAC1B,OAAO,GAAE,WAAgB,EACzB,UAAU,CAAC,EAAE,UAAU;IACvB,uEAAuE;IACvE,YAAY,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,GAC3C,OAAO,CAAC,YAAY,CAAC;CA8BzB"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
2
|
+
import { correctContextWindow, withNative1MSuffix } from '@hammoc/shared';
|
|
2
3
|
import path from 'path';
|
|
3
4
|
import fs from 'fs/promises';
|
|
4
5
|
import { execSync } from 'child_process';
|
|
5
6
|
import { InvalidPathError, parseSDKError } from '../utils/errors.js';
|
|
6
7
|
import { StreamHandler } from './streamHandler.js';
|
|
8
|
+
import { SessionService } from './sessionService.js';
|
|
7
9
|
import { createLogger } from '../utils/logger.js';
|
|
8
10
|
const log = createLogger('chatService');
|
|
9
11
|
/**
|
|
@@ -174,7 +176,10 @@ export class ChatService {
|
|
|
174
176
|
disallowedTools: resolvedDisallowed.length > 0 ? resolvedDisallowed : undefined,
|
|
175
177
|
maxTurns: options.maxTurns,
|
|
176
178
|
abortController: options.abortController,
|
|
177
|
-
|
|
179
|
+
// Append `[1m]` for native 1M models — the SDK caps the auto-compact
|
|
180
|
+
// window at the model's native size, and only recognizes 1M capacity
|
|
181
|
+
// when the model string carries this suffix (see `fX()` in claude.exe).
|
|
182
|
+
model: withNative1MSuffix(options.model) || undefined,
|
|
178
183
|
resume: options.resume,
|
|
179
184
|
sessionId: options.sessionId,
|
|
180
185
|
includePartialMessages: true, // Enable real-time streaming
|
|
@@ -183,6 +188,10 @@ export class ChatService {
|
|
|
183
188
|
maxThinkingTokens: options.maxThinkingTokens,
|
|
184
189
|
maxBudgetUsd: options.maxBudgetUsd,
|
|
185
190
|
effort: options.effort,
|
|
191
|
+
// Explicit thinking config for adaptive-thinking models. On Opus 4.7 this
|
|
192
|
+
// opts back in to `display: 'summarized'` so ThinkingBlock UI stays visible
|
|
193
|
+
// (the API flipped the default to 'omitted' starting 2026-04-16).
|
|
194
|
+
...(options.thinking ? { thinking: options.thinking } : {}),
|
|
186
195
|
resumeSessionAt: options.resumeSessionAt,
|
|
187
196
|
forkSession: options.forkSession,
|
|
188
197
|
enableFileCheckpointing: options.enableFileCheckpointing,
|
|
@@ -203,6 +212,22 @@ export class ChatService {
|
|
|
203
212
|
if (queryOptions.resumeSessionAt) {
|
|
204
213
|
log.info(`resumeSessionAt branch: assistantUuid="${queryOptions.resumeSessionAt}", resume="${queryOptions.resume}"`);
|
|
205
214
|
}
|
|
215
|
+
// Strip empty user messages left by rewind before SDK reads the JSONL.
|
|
216
|
+
// SDK query({ prompt: '' }) used for file rewind writes an empty text
|
|
217
|
+
// block that triggers cache_control 400 errors on subsequent API calls.
|
|
218
|
+
const resumeSessionId = queryOptions.resume;
|
|
219
|
+
if (resumeSessionId && this.workingDirectory) {
|
|
220
|
+
try {
|
|
221
|
+
const sessionService = new SessionService();
|
|
222
|
+
const cleaned = sessionService.cleanRewindDirty(this.workingDirectory, resumeSessionId);
|
|
223
|
+
if (cleaned) {
|
|
224
|
+
log.info(`Cleaned rewind-dirty JSONL for session ${resumeSessionId}`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
catch (err) {
|
|
228
|
+
log.warn(`cleanRewindDirty failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
206
231
|
// Use AsyncIterable prompt when images are present (Story 5.5)
|
|
207
232
|
const { images } = options;
|
|
208
233
|
if (images && images.length > 0) {
|
|
@@ -264,7 +289,7 @@ export class ChatService {
|
|
|
264
289
|
cacheReadInputTokens: msg.usage.cache_read_input_tokens ?? 0,
|
|
265
290
|
cacheCreationInputTokens: msg.usage.cache_creation_input_tokens ?? 0,
|
|
266
291
|
totalCostUSD: msg.total_cost_usd,
|
|
267
|
-
contextWindow: extractContextWindow(msg.modelUsage),
|
|
292
|
+
contextWindow: correctContextWindow(extractContextWindow(msg.modelUsage), msg.modelUsage ? Object.keys(msg.modelUsage)[0] : undefined),
|
|
268
293
|
},
|
|
269
294
|
};
|
|
270
295
|
}
|