@cartanova/qgrid-cli 1.5.5 → 1.6.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.
Files changed (49) hide show
  1. package/bundle/dist/application/qgrid/oauth.js +1 -1
  2. package/bundle/dist/application/qgrid/qgrid.dispatcher.js +166 -0
  3. package/bundle/dist/application/qgrid/qgrid.frame.js +28 -36
  4. package/bundle/dist/application/qgrid/qgrid.types.js +5 -16
  5. package/bundle/dist/application/queries.generated.js +1 -1
  6. package/bundle/dist/application/sonamu.generated.js +1 -1
  7. package/bundle/dist/application/sonamu.generated.sso.js +1 -1
  8. package/bundle/dist/sonamu.config.js +6 -9
  9. package/bundle/src/application/qgrid/oauth.ts +1 -1
  10. package/bundle/src/application/qgrid/qgrid.dispatcher.ts +184 -0
  11. package/bundle/src/application/qgrid/qgrid.frame.ts +28 -50
  12. package/bundle/src/application/qgrid/qgrid.types.ts +2 -14
  13. package/bundle/src/application/queries.generated.ts +1 -0
  14. package/bundle/src/application/sonamu.generated.http +2 -1
  15. package/bundle/src/application/sonamu.generated.sso.ts +6 -5
  16. package/bundle/src/application/sonamu.generated.ts +1 -0
  17. package/bundle/src/sonamu.config.ts +4 -7
  18. package/bundle/web-dist/client/assets/index-BRZCFaFz.css +1 -0
  19. package/bundle/web-dist/client/assets/index-D8eEjsZj.js +78 -0
  20. package/bundle/web-dist/client/assets/{logs-CQDBOCud.js → logs-CKnJzuH6.js} +1 -1
  21. package/bundle/web-dist/client/assets/{routes-MR1DKizN.js → routes-DQKecVGa.js} +1 -1
  22. package/bundle/web-dist/client/assets/sd.generated-NHYHS_-0.js +47 -0
  23. package/bundle/web-dist/client/assets/services.generated-DDVXMid7.js +1 -0
  24. package/bundle/web-dist/client/assets/{show--z3WxDb0.js → show-D2z1qxJ5.js} +1 -1
  25. package/bundle/web-dist/client/assets/tokens-BaywaQkm.js +1 -0
  26. package/bundle/web-dist/client/assets/vendor-tanstack-DJRQAbrY.js +1 -0
  27. package/bundle/web-dist/client/index.html +4 -4
  28. package/bundle/web-dist/server/assets/{copy-GKsNP-2_.js → copy-BVWDOV2T.js} +1 -1
  29. package/bundle/web-dist/server/assets/{lazyRouteComponent-B78WDGgM.js → lazyRouteComponent-BJmwxFyJ.js} +2 -128
  30. package/bundle/web-dist/server/assets/{logs-BV6gEe15.js → logs-DgIbufNf.js} +4 -4
  31. package/bundle/web-dist/server/assets/{routes-B5FkWLUe.js → routes-x7-hqUm0.js} +3 -3
  32. package/bundle/web-dist/server/assets/{sd.generated-Mnbmi4YR.js → sd.generated-BZPIp4uL.js} +122 -1
  33. package/bundle/web-dist/server/assets/{services.generated-DjdxFvCg.js → services.generated-BA0gbdmd.js} +134 -20
  34. package/bundle/web-dist/server/assets/shim-DGrmZkac.js +129 -0
  35. package/bundle/web-dist/server/assets/{show-BqSxVXai.js → show-Bk3NayMH.js} +4 -4
  36. package/bundle/web-dist/server/assets/{tokens-BGaTdsEb.js → tokens-CVSwt0x0.js} +13 -24
  37. package/bundle/web-dist/server/entry-server.generated.js +19679 -17705
  38. package/package.json +2 -2
  39. package/bundle/dist/application/qgrid/pool.js +0 -128
  40. package/bundle/dist/application/qgrid/worker.js +0 -189
  41. package/bundle/src/application/qgrid/pool.ts +0 -165
  42. package/bundle/src/application/qgrid/worker.ts +0 -240
  43. package/bundle/web-dist/client/assets/index-DLrkHIo2.js +0 -116
  44. package/bundle/web-dist/client/assets/index-kQRqXaWM.css +0 -1
  45. package/bundle/web-dist/client/assets/sd.generated-DXtkTTGn.js +0 -47
  46. package/bundle/web-dist/client/assets/services.generated-C0OpNm5q.js +0 -1
  47. package/bundle/web-dist/client/assets/tokens-Bch6XO9K.js +0 -1
  48. package/bundle/web-dist/client/assets/vendor-tanstack-CUxlo6YN.js +0 -1
  49. /package/bundle/web-dist/server/assets/{cost-D0Ta7MJa.js → cost-DdHTzQDR.js} +0 -0
@@ -1,240 +0,0 @@
1
- /**
2
- * Worker — Claude CLI stream-json 프로세스 하나를 관리.
3
- *
4
- * 기존 SocratsAI ClaudeCliService에서 추출 + 리팩터:
5
- * - 토큰/모델을 생성자에서 주입
6
- * - env allowlist (PATH, TMPDIR, CLAUDE_CODE_OAUTH_TOKEN + CLAUDE_CODE_DISABLE_* )
7
- * - callCount 추적 + maxCalls 도달 시 프로세스 재활용
8
- * - QuotaError/TimeoutError/ProcessError 구분
9
- */
10
- import { type ChildProcess, spawn } from "node:child_process";
11
- import { mkdirSync } from "node:fs";
12
-
13
- import { type CliResult, type QueryInput } from "./qgrid.types";
14
- import { maskToken, ProcessError, QuotaError, TimeoutError } from "./qgrid.types";
15
-
16
- type PendingRequest = {
17
- resolve: (value: CliResult) => void;
18
- reject: (reason: Error) => void;
19
- timer: ReturnType<typeof setTimeout>;
20
- };
21
-
22
- export type WorkerConfig = {
23
- token: string;
24
- model: string;
25
- timeout: number;
26
- cwd: string;
27
- maxCalls: number;
28
- };
29
-
30
- export class Worker {
31
- tokenId: string;
32
- config: WorkerConfig;
33
- process: ChildProcess | null = null;
34
- buffer = "";
35
- pending: PendingRequest | null = null;
36
- sessionId: string | null = null;
37
- queue: Array<() => void> = [];
38
- cwdCreated = false;
39
- callCount = 0;
40
- needsRecycle = false;
41
-
42
- constructor(config: WorkerConfig) {
43
- this.config = config;
44
- this.tokenId = config.token;
45
- }
46
-
47
- getQueueDepth(): number {
48
- return this.queue.length + (this.pending ? 1 : 0);
49
- }
50
-
51
- rejectPending(err: Error): void {
52
- if (!this.pending) return;
53
- this.pending.reject(err);
54
- clearTimeout(this.pending.timer);
55
- this.pending = null;
56
- }
57
-
58
- ensureProcess(): ChildProcess {
59
- if (this.process && this.process.exitCode === null && !this.needsRecycle) {
60
- return this.process;
61
- }
62
-
63
- if (this.process && this.process.exitCode === null) {
64
- this.process.kill();
65
- this.process = null;
66
- }
67
-
68
- const env: NodeJS.ProcessEnv = {
69
- PATH: process.env.PATH,
70
- TMPDIR: process.env.TMPDIR,
71
- CLAUDE_CODE_OAUTH_TOKEN: this.config.token,
72
- CLAUDE_CODE_DISABLE_AUTO_MEMORY: "1",
73
- CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING: "1",
74
- CLAUDE_CODE_DISABLE_1M_CONTEXT: "1",
75
- };
76
-
77
- const { cwd } = this.config;
78
- if (!this.cwdCreated) {
79
- mkdirSync(cwd, { recursive: true });
80
- this.cwdCreated = true;
81
- }
82
-
83
- const child = spawn(
84
- "claude",
85
- [
86
- "-p",
87
- "--input-format",
88
- "stream-json",
89
- "--output-format",
90
- "stream-json",
91
- "--verbose",
92
- "--max-turns",
93
- "1",
94
- "--permission-mode",
95
- "bypassPermissions",
96
- "--setting-sources",
97
- "project",
98
- "--model",
99
- this.config.model,
100
- ],
101
- { stdio: ["pipe", "pipe", "ignore"], env, cwd },
102
- );
103
-
104
- child.stdout?.on("data", (d: Buffer) => {
105
- this.buffer += d.toString();
106
- this.processBuffer();
107
- });
108
-
109
- child.on("close", () => {
110
- this.process = null;
111
- this.rejectPending(
112
- new ProcessError(`CLI process closed (token: ${maskToken(this.tokenId)})`),
113
- );
114
- this.drainQueue();
115
- });
116
-
117
- child.on("error", (err) => {
118
- this.process = null;
119
- this.rejectPending(
120
- new ProcessError(`CLI process error: ${err.message} (token: ${maskToken(this.tokenId)})`),
121
- );
122
- this.drainQueue();
123
- });
124
-
125
- this.process = child;
126
- this.buffer = "";
127
- this.sessionId = null;
128
- this.callCount = 0;
129
- this.needsRecycle = false;
130
- return child;
131
- }
132
-
133
- processBuffer(): void {
134
- const lines = this.buffer.split("\n");
135
- this.buffer = lines.pop() ?? "";
136
-
137
- lines
138
- .filter((line) => line.trim() !== "")
139
- .forEach((line) => {
140
- try {
141
- const j = JSON.parse(line);
142
-
143
- if (j.type === "system" && j.subtype === "init" && j.session_id) {
144
- this.sessionId = j.session_id;
145
- }
146
-
147
- if (j.type === "result" && this.pending) {
148
- let text: string = j.result ?? "";
149
- text = text.replace(/^```(?:json)?\s*\n?/i, "").replace(/\n?```\s*$/i, "");
150
-
151
- if (text.startsWith("You've hit")) {
152
- this.pending.reject(
153
- new QuotaError(`Quota exhausted (token: ${maskToken(this.tokenId)})`),
154
- );
155
- clearTimeout(this.pending.timer);
156
- this.pending = null;
157
- this.drainQueue();
158
- return;
159
- }
160
-
161
- const u = j.usage ?? {};
162
- this.pending.resolve({
163
- text,
164
- usage: {
165
- input_tokens: u.input_tokens ?? 0,
166
- output_tokens: u.output_tokens ?? 0,
167
- cache_creation_input_tokens: u.cache_creation_input_tokens ?? 0,
168
- cache_read_input_tokens: u.cache_read_input_tokens ?? 0,
169
- },
170
- durationMs: j.duration_ms ?? 0,
171
- costUsd: j.total_cost_usd ?? 0,
172
- });
173
- clearTimeout(this.pending.timer);
174
- this.pending = null;
175
- this.drainQueue();
176
- }
177
- } catch {
178
- // skip non-json lines
179
- }
180
- });
181
- }
182
-
183
- drainQueue(): void {
184
- if (this.pending) return;
185
- const next = this.queue.shift();
186
- if (next) next();
187
- }
188
-
189
- async query(input: QueryInput, timeoutMs?: number): Promise<CliResult> {
190
- if (this.pending) {
191
- await new Promise<void>((resolve) => {
192
- this.queue.push(resolve);
193
- });
194
- }
195
-
196
- const child = this.ensureProcess();
197
- const timeout = timeoutMs ?? this.config.timeout;
198
-
199
- this.callCount++;
200
- if (this.callCount >= this.config.maxCalls) {
201
- this.needsRecycle = true;
202
- }
203
-
204
- const prompt = input.system ? `${input.system}\n\n${input.prompt}` : input.prompt;
205
-
206
- return new Promise<CliResult>((resolve, reject) => {
207
- const timer = setTimeout(() => {
208
- this.pending = null;
209
- reject(
210
- new TimeoutError(`Timeout after ${timeout / 1000}s (token: ${maskToken(this.tokenId)})`),
211
- );
212
- this.kill();
213
- }, timeout);
214
-
215
- this.pending = { resolve, reject, timer };
216
-
217
- const msg = JSON.stringify({
218
- type: "user",
219
- message: { role: "user", content: prompt },
220
- session_id: this.sessionId ?? "default",
221
- parent_tool_use_id: null,
222
- });
223
-
224
- child.stdin?.write(`${msg}\n`);
225
- });
226
- }
227
-
228
- kill(): void {
229
- if (this.process && this.process.exitCode === null) {
230
- this.process.kill();
231
- }
232
- this.process = null;
233
- this.buffer = "";
234
- this.sessionId = null;
235
- this.callCount = 0;
236
- this.needsRecycle = false;
237
- this.rejectPending(new ProcessError(`Worker killed (token: ${maskToken(this.tokenId)})`));
238
- this.drainQueue();
239
- }
240
- }