@tienne/gestalt 0.116.0 → 0.118.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.ko.md +1 -1
- package/README.md +1 -1
- package/dist/package.json +1 -1
- package/dist/plugin/role-agents/lens-reader/AGENT.md +1 -1
- package/dist/plugin/role-agents/video-summarizer/AGENT.md +10 -4
- package/dist/plugin/skills/share/SKILL.md +39 -6
- package/dist/plugin/skills/share/agents/openai.yaml +1 -1
- package/dist/plugin/skills/video-digest/SKILL.md +2 -1
- package/dist/plugin/skills/video-digest/templates/visual.md +2 -0
- package/dist/src/cli/commands/peer.d.ts +11 -1
- package/dist/src/cli/commands/peer.d.ts.map +1 -1
- package/dist/src/cli/commands/peer.js +113 -5
- package/dist/src/cli/commands/peer.js.map +1 -1
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +6 -3
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/digest/blocks.d.ts +1330 -280
- package/dist/src/digest/blocks.d.ts.map +1 -1
- package/dist/src/digest/diagram-schema.d.ts +239 -1
- package/dist/src/digest/diagram-schema.d.ts.map +1 -1
- package/dist/src/digest/diagram-schema.js +27 -0
- package/dist/src/digest/diagram-schema.js.map +1 -1
- package/dist/src/digest/lint-extension.d.ts +4 -1
- package/dist/src/digest/lint-extension.d.ts.map +1 -1
- package/dist/src/digest/lint-extension.js +80 -1
- package/dist/src/digest/lint-extension.js.map +1 -1
- package/dist/src/digest/lint.js +1 -1
- package/dist/src/digest/lint.js.map +1 -1
- package/dist/src/digest/render-blocks.d.ts +4 -1
- package/dist/src/digest/render-blocks.d.ts.map +1 -1
- package/dist/src/digest/render-blocks.js +43 -3
- package/dist/src/digest/render-blocks.js.map +1 -1
- package/dist/src/digest/render-html.d.ts.map +1 -1
- package/dist/src/digest/render-html.js +47 -2
- package/dist/src/digest/render-html.js.map +1 -1
- package/dist/src/digest/schema.d.ts +3250 -478
- package/dist/src/digest/schema.d.ts.map +1 -1
- package/dist/src/digest/schema.js +1 -1
- package/dist/src/digest/svg.d.ts +28 -0
- package/dist/src/digest/svg.d.ts.map +1 -1
- package/dist/src/digest/svg.js +196 -12
- package/dist/src/digest/svg.js.map +1 -1
- package/dist/src/digest/theme-diary.d.ts +1 -0
- package/dist/src/digest/theme-diary.d.ts.map +1 -1
- package/dist/src/digest/theme-diary.js +2 -1
- package/dist/src/digest/theme-diary.js.map +1 -1
- package/dist/src/digest/viewer-js.d.ts.map +1 -1
- package/dist/src/digest/viewer-js.js +41 -0
- package/dist/src/digest/viewer-js.js.map +1 -1
- package/dist/src/mcp/tools/peer.d.ts.map +1 -1
- package/dist/src/mcp/tools/peer.js +16 -1
- package/dist/src/mcp/tools/peer.js.map +1 -1
- package/dist/src/peer/client.d.ts +5 -1
- package/dist/src/peer/client.d.ts.map +1 -1
- package/dist/src/peer/client.js +6 -2
- package/dist/src/peer/client.js.map +1 -1
- package/dist/src/peer/detach.d.ts +114 -0
- package/dist/src/peer/detach.d.ts.map +1 -0
- package/dist/src/peer/detach.js +339 -0
- package/dist/src/peer/detach.js.map +1 -0
- package/dist/src/peer/lock.d.ts +6 -0
- package/dist/src/peer/lock.d.ts.map +1 -1
- package/dist/src/peer/lock.js +17 -1
- package/dist/src/peer/lock.js.map +1 -1
- package/package.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/.mcp.json +1 -1
- package/plugin/mcp.json +1 -1
- package/plugin/role-agents/lens-reader/AGENT.md +1 -1
- package/plugin/role-agents/video-summarizer/AGENT.md +10 -4
- package/plugin/skills/share/SKILL.md +39 -6
- package/plugin/skills/share/agents/openai.yaml +1 -1
- package/plugin/skills/video-digest/SKILL.md +2 -1
- package/plugin/skills/video-digest/templates/visual.md +2 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { closeSync, constants, fchmodSync, fstatSync, ftruncateSync, openSync, readSync, writeSync, } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { request } from './client.js';
|
|
5
|
+
import { lockPath, processAlive, readLockPid } from './lock.js';
|
|
6
|
+
import { plainLabel } from './message.js';
|
|
7
|
+
import { ensurePrivateDir, socketPath } from './paths.js';
|
|
8
|
+
/**
|
|
9
|
+
* 떨어져 뜬 데몬의 로그 상한. 데몬은 뜰 때 안내 몇 줄과 실패만 적어서 평소에는 거의 안 는다. 넘으면 지금 로그를
|
|
10
|
+
* `daemon.log.1`로 복사하고 비운다. 그래서 디스크에 남는 건 상한의 두 배 남짓이다
|
|
11
|
+
*/
|
|
12
|
+
export const DAEMON_LOG_MAX_BYTES = 1024 * 1024;
|
|
13
|
+
/** 떨어져 뜬 데몬이 로그 크기를 보는 간격 */
|
|
14
|
+
export const DAEMON_LOG_CHECK_MS = 60_000;
|
|
15
|
+
/** `--detach`가 소켓 답을 기다리는 시간과 `--stop`이 프로세스가 끝나길 기다리는 시간의 기본값 */
|
|
16
|
+
export const DEFAULT_DAEMON_WAIT_MS = 10_000;
|
|
17
|
+
/**
|
|
18
|
+
* `--detach`가 자식에 거는 환경 변수. 자식은 이걸 보고 로그 크기를 챙기고 안내 문구를 바꾼 뒤 지운다.
|
|
19
|
+
* 멈추는 길이나 잠금 규칙은 이 값과 상관없이 같다
|
|
20
|
+
*/
|
|
21
|
+
export const DETACHED_ENV = 'GESTALT_PEER_DETACHED';
|
|
22
|
+
/** 이번 기동부터 로그 꼬리를 자르는 표시 줄의 앞머리 */
|
|
23
|
+
const MARKER = '=== gestalt peer daemon --detach';
|
|
24
|
+
const POLL_MS = 100;
|
|
25
|
+
/** 데몬에 넘기지 않는 Node 옵션. 디버거 포트가 겹치거나 파일이 바뀔 때마다 데몬이 다시 뜬다 */
|
|
26
|
+
const DEV_FLAG = /^--(inspect|debug|watch)/;
|
|
27
|
+
export function daemonLogPath(root) {
|
|
28
|
+
return join(root, 'daemon.log');
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 로그가 상한을 넘었으면 `.1`로 복사하고 비운다. 이름을 옮기지 않는 건 떠 있는 데몬이 열어 둔 파일을
|
|
32
|
+
* 계속 쓰기 때문이다. 옮기면 데몬은 `.1`에 쓰고 원래 이름의 파일은 다시 안 큰다. 열 때 `O_APPEND`라서
|
|
33
|
+
* 비운 뒤에 쓰는 줄은 파일 앞에서부터 다시 쌓인다. 복사와 비우기 사이에 쓰인 줄은 잃을 수 있다.
|
|
34
|
+
*
|
|
35
|
+
* 두 파일 다 `O_NOFOLLOW`로 열어 연 fd로만 읽고 쓰고 비운다. 경로로 다시 열면 확인한 파일과 쓰는 파일이
|
|
36
|
+
* 다를 수 있다. 원본이 없거나 심링크면 아무것도 안 하고 false다. `.1`이 심링크면 던진다.
|
|
37
|
+
*/
|
|
38
|
+
export function rotateDaemonLog(path, max = DAEMON_LOG_MAX_BYTES) {
|
|
39
|
+
let src;
|
|
40
|
+
try {
|
|
41
|
+
src = openSync(path, constants.O_RDWR | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const st = fstatSync(src);
|
|
48
|
+
if (!st.isFile() || st.size <= max)
|
|
49
|
+
return false;
|
|
50
|
+
const old = `${path}.1`;
|
|
51
|
+
const dst = openSync(old, constants.O_WRONLY |
|
|
52
|
+
constants.O_CREAT |
|
|
53
|
+
constants.O_TRUNC |
|
|
54
|
+
constants.O_NOFOLLOW |
|
|
55
|
+
constants.O_NONBLOCK, 0o600);
|
|
56
|
+
try {
|
|
57
|
+
if (!fstatSync(dst).isFile())
|
|
58
|
+
throw new Error(`peer 로그 자리에 다른 파일이 있어요: ${old}`);
|
|
59
|
+
fchmodSync(dst, 0o600);
|
|
60
|
+
const buf = Buffer.alloc(64 * 1024);
|
|
61
|
+
for (let pos = 0;;) {
|
|
62
|
+
const n = readSync(src, buf, 0, buf.length, pos);
|
|
63
|
+
if (n === 0)
|
|
64
|
+
break;
|
|
65
|
+
writeSync(dst, buf, 0, n);
|
|
66
|
+
pos += n;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
closeSync(dst);
|
|
71
|
+
}
|
|
72
|
+
ftruncateSync(src, 0);
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
closeSync(src);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* 로그를 덧붙이기로 연다. 없으면 0600으로 만들고 있으면 권한을 다시 0600으로 좁힌다. 심링크면 따라가지
|
|
81
|
+
* 않고 실패한다. 디렉토리가 0700이라 남이 링크를 걸 수는 없지만 내가 실수로 둔 링크로 남의 파일을 쓰지
|
|
82
|
+
* 않게 한다
|
|
83
|
+
*/
|
|
84
|
+
export function openDaemonLog(path) {
|
|
85
|
+
const fd = openSync(path, constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT | constants.O_NOFOLLOW, 0o600);
|
|
86
|
+
try {
|
|
87
|
+
if (!fstatSync(fd).isFile())
|
|
88
|
+
throw new Error(`peer 로그 자리에 다른 파일이 있어요: ${path}`);
|
|
89
|
+
fchmodSync(fd, 0o600);
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
closeSync(fd);
|
|
93
|
+
throw err;
|
|
94
|
+
}
|
|
95
|
+
return fd;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* 이번 기동의 표시 줄 뒤에서 마지막 몇 줄. 표시 줄이 없으면 끝에서 센다. 데몬 오류에는 릴레이나 팀원이
|
|
99
|
+
* 보낸 글자가 섞일 수 있어서 터미널과 모델에 그대로 내지 않고 줄마다 한 줄 라벨로 정리한다
|
|
100
|
+
*/
|
|
101
|
+
export function logTail(path, lines = 20) {
|
|
102
|
+
let text;
|
|
103
|
+
try {
|
|
104
|
+
const fd = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
105
|
+
try {
|
|
106
|
+
const size = fstatSync(fd).size;
|
|
107
|
+
const len = Math.min(size, 64 * 1024);
|
|
108
|
+
const buf = Buffer.alloc(len);
|
|
109
|
+
readSync(fd, buf, 0, len, size - len);
|
|
110
|
+
text = buf.toString('utf8');
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
closeSync(fd);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
const at = text.lastIndexOf(MARKER);
|
|
120
|
+
if (at !== -1)
|
|
121
|
+
text = text.slice(text.indexOf('\n', at) + 1);
|
|
122
|
+
return text
|
|
123
|
+
.split('\n')
|
|
124
|
+
.map((l) => plainLabel(l, 300))
|
|
125
|
+
.filter((l) => l !== undefined && l.trim() !== '')
|
|
126
|
+
.slice(-lines);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* 자식으로 띄울 명령. 지금 프로세스와 같은 Node와 실행 인자에 같은 스크립트를 주고 `peer daemon`만
|
|
130
|
+
* 붙인다. `pnpm tsx bin/gestalt.ts`로 불렀으면 tsx가 건 `--require`, `--import`가 실행 인자에 들어 있어서
|
|
131
|
+
* 그대로 따라간다. 설치본이면 실행 인자는 비고 스크립트가 `dist/bin/gestalt.js`다. 디버거와 감시 옵션
|
|
132
|
+
* (`DEV_FLAG`)은 데몬에 넘기지 않는다
|
|
133
|
+
*/
|
|
134
|
+
export function daemonCommand(argv = process.argv, execArgv = process.execArgv, execPath = process.execPath) {
|
|
135
|
+
const script = argv[1];
|
|
136
|
+
if (!script)
|
|
137
|
+
throw new Error('gestalt 실행 경로를 못 찾았어요');
|
|
138
|
+
const flags = execArgv.filter((a) => !DEV_FLAG.test(a));
|
|
139
|
+
return [execPath, ...flags, script, 'peer', 'daemon'];
|
|
140
|
+
}
|
|
141
|
+
/** 소켓에 답한 데몬 pid. 안 떠 있거나 시한(기본 1초) 안에 안 답하면 undefined다 */
|
|
142
|
+
export async function answeringDaemonPid(sock, timeoutMs = 1_000) {
|
|
143
|
+
try {
|
|
144
|
+
const res = await request(sock, { op: 'status' }, timeoutMs);
|
|
145
|
+
return res.ok ? res.result.pid : undefined;
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/** 떨어진 데몬이 시한 안에 안 떴을 때. 로그 꼬리를 같이 들고 간다 */
|
|
152
|
+
export class DaemonDetachError extends Error {
|
|
153
|
+
log;
|
|
154
|
+
tail;
|
|
155
|
+
child;
|
|
156
|
+
constructor(message, log, tail,
|
|
157
|
+
/** 띄운 자식 pid. 시한이 지났으면 SIGTERM을 보냈다 */
|
|
158
|
+
child) {
|
|
159
|
+
super(message);
|
|
160
|
+
this.log = log;
|
|
161
|
+
this.tail = tail;
|
|
162
|
+
this.child = child;
|
|
163
|
+
this.name = 'DaemonDetachError';
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function sleep(ms) {
|
|
167
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* 자식에 넘길 환경. 부른 셸의 환경을 그대로 물려주되 세 가지만 바꾼다. 루트는 부모가 쓴 값으로 고정한다.
|
|
171
|
+
* 부른 Claude Code 세션 표시(`CLAUDE_PID`, `CLAUDE_CODE_SESSION_ID`)는 뺀다. 데몬은 그 세션보다 오래 살아서
|
|
172
|
+
* 그 값이 곧 틀린 값이 된다. `NODE_OPTIONS`에서는 실행 인자처럼 `DEV_FLAG`에 걸리는 옵션을 뺀다.
|
|
173
|
+
*
|
|
174
|
+
* 허용 목록으로 좁히지 않는 건 데몬이 `CLAUDE_CONFIG_DIR`, `CODEX_HOME`, `HOME`, CA 설정 같은 값으로 세션과
|
|
175
|
+
* 릴레이를 찾기 때문이다. 빠뜨리면 다른 설정 디렉토리를 보고 조용히 엉뚱하게 돈다
|
|
176
|
+
*/
|
|
177
|
+
export function detachedEnv(env, root) {
|
|
178
|
+
const out = { ...env, GESTALT_PEER_HOME: root, [DETACHED_ENV]: '1' };
|
|
179
|
+
delete out['CLAUDE_PID'];
|
|
180
|
+
delete out['CLAUDE_CODE_SESSION_ID'];
|
|
181
|
+
const nodeOptions = out['NODE_OPTIONS'];
|
|
182
|
+
if (nodeOptions !== undefined) {
|
|
183
|
+
const kept = nodeOptions
|
|
184
|
+
.split(/\s+/)
|
|
185
|
+
.filter((t) => t !== '' && !DEV_FLAG.test(t))
|
|
186
|
+
.join(' ');
|
|
187
|
+
if (kept === '')
|
|
188
|
+
delete out['NODE_OPTIONS'];
|
|
189
|
+
else
|
|
190
|
+
out['NODE_OPTIONS'] = kept;
|
|
191
|
+
}
|
|
192
|
+
return out;
|
|
193
|
+
}
|
|
194
|
+
export function assertDetachSupported(platform = process.platform) {
|
|
195
|
+
// 데몬이 유닉스 소켓과 0700 디렉토리 권한에 기대고 훅도 bash다. Windows에서는 데몬 자체가 안 돈다
|
|
196
|
+
if (platform === 'win32') {
|
|
197
|
+
throw new Error('peer 데몬은 macOS와 Linux에서만 떠요. Windows는 지원하지 않아요');
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* 데몬을 이 프로세스와 떨어진 새 프로세스 세션으로 띄우고 소켓이 답할 때까지 기다린다.
|
|
202
|
+
*
|
|
203
|
+
* 이미 떠 있는지는 소켓 답으로 본다. 둘이 동시에 불러 둘 다 자식을 띄워도 잠금(`peer.lock`)을 하나만
|
|
204
|
+
* 잡으므로 데몬은 하나다. 진 자식은 "이미 떠 있어요"로 끝나고 그 부모는 이긴 데몬의 pid를 `already`로
|
|
205
|
+
* 받는다. 시한이 지나면 아직 살아 있는 내 자식에 SIGTERM을 보내고 로그 꼬리와 함께 던진다. 늦게라도
|
|
206
|
+
* 뜬 데몬이 실패 보고 뒤에 남지 않게 하려는 것이다.
|
|
207
|
+
*/
|
|
208
|
+
export async function detachDaemon(options) {
|
|
209
|
+
assertDetachSupported();
|
|
210
|
+
const { root } = options;
|
|
211
|
+
const waitMs = options.waitMs ?? DEFAULT_DAEMON_WAIT_MS;
|
|
212
|
+
ensurePrivateDir(root);
|
|
213
|
+
const sock = socketPath(root);
|
|
214
|
+
const log = daemonLogPath(root);
|
|
215
|
+
const running = await answeringDaemonPid(sock);
|
|
216
|
+
if (running !== undefined)
|
|
217
|
+
return { pid: running, log, already: true };
|
|
218
|
+
// 로그 크기 챙기기는 곁다리다. 실패해도 띄우고 이유만 돌려준다. 아래 openDaemonLog가 심링크는 따로 막는다
|
|
219
|
+
let rotateError;
|
|
220
|
+
try {
|
|
221
|
+
rotateDaemonLog(log);
|
|
222
|
+
}
|
|
223
|
+
catch (err) {
|
|
224
|
+
rotateError = err instanceof Error ? err.message : String(err);
|
|
225
|
+
}
|
|
226
|
+
const [cmd, ...args] = options.command ?? daemonCommand();
|
|
227
|
+
if (!cmd)
|
|
228
|
+
throw new Error('띄울 명령이 비었어요');
|
|
229
|
+
const fd = openDaemonLog(log);
|
|
230
|
+
let child;
|
|
231
|
+
try {
|
|
232
|
+
writeSync(fd, `${MARKER} ${new Date().toISOString()} ===\n`);
|
|
233
|
+
child = spawn(cmd, args, {
|
|
234
|
+
detached: true,
|
|
235
|
+
stdio: ['ignore', fd, fd],
|
|
236
|
+
// 데몬은 부른 워크트리보다 오래 산다. 그 디렉토리를 붙잡지 않게 데몬 루트에서 띄운다
|
|
237
|
+
cwd: root,
|
|
238
|
+
env: detachedEnv(options.env ?? process.env, root),
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
finally {
|
|
242
|
+
// 자식이 제 사본을 들고 있다. 부모 것은 닫아야 부모가 끝날 때 붙잡는 게 없다
|
|
243
|
+
closeSync(fd);
|
|
244
|
+
}
|
|
245
|
+
child.unref();
|
|
246
|
+
let exited = false;
|
|
247
|
+
let spawnError;
|
|
248
|
+
child.once('exit', () => {
|
|
249
|
+
exited = true;
|
|
250
|
+
});
|
|
251
|
+
child.once('error', (err) => {
|
|
252
|
+
spawnError = err;
|
|
253
|
+
exited = true;
|
|
254
|
+
});
|
|
255
|
+
const fail = (message) => {
|
|
256
|
+
throw new DaemonDetachError(message, log, logTail(log), child.pid);
|
|
257
|
+
};
|
|
258
|
+
const deadline = Date.now() + waitMs;
|
|
259
|
+
while (Date.now() < deadline) {
|
|
260
|
+
// 묻는 시한을 남은 시간으로 줄여 --wait를 넘기지 않는다
|
|
261
|
+
const pid = await answeringDaemonPid(sock, Math.max(1, Math.min(1_000, deadline - Date.now())));
|
|
262
|
+
if (pid !== undefined) {
|
|
263
|
+
// 자식이 곧 데몬이라는 가정이다(DetachOptions.command). 다르면 다른 데몬이 잠금을 먼저 잡은 것이다
|
|
264
|
+
return {
|
|
265
|
+
pid,
|
|
266
|
+
log,
|
|
267
|
+
already: pid !== child.pid,
|
|
268
|
+
...(child.pid ? { spawned: child.pid } : {}),
|
|
269
|
+
...(rotateError !== undefined ? { rotateError } : {}),
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
if (spawnError)
|
|
273
|
+
fail(`peer 데몬을 못 띄웠어요: ${spawnError.message}`);
|
|
274
|
+
if (exited) {
|
|
275
|
+
// 다른 데몬이 잠금을 쥐고 뜨는 중이면 그 소켓을 마저 기다린다
|
|
276
|
+
const holder = readLockPid(root);
|
|
277
|
+
if (holder === undefined || holder === child.pid || !processAlive(holder)) {
|
|
278
|
+
fail('peer 데몬이 뜨다가 끝났어요');
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
await sleep(POLL_MS);
|
|
282
|
+
}
|
|
283
|
+
if (!exited && child.pid !== undefined) {
|
|
284
|
+
try {
|
|
285
|
+
process.kill(child.pid, 'SIGTERM');
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
// 그새 끝났다
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
const holder = readLockPid(root);
|
|
292
|
+
const secs = Math.round(waitMs / 100) / 10;
|
|
293
|
+
if (exited && holder !== undefined && holder !== child.pid && processAlive(holder)) {
|
|
294
|
+
fail(`peer 데몬이 ${secs}초 안에 안 떴어요. 잠금(${lockPath(root)})을 쥔 pid ${holder}가 소켓에 답하지 않아요`);
|
|
295
|
+
}
|
|
296
|
+
return fail(`peer 데몬이 ${secs}초 안에 안 떴어요`);
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* 데몬에 SIGTERM을 보내고 끝나길 기다린다. 신호를 보내기 전에 소켓에 답한 데몬 pid와 잠금 파일의 pid가
|
|
300
|
+
* 같은지 본다. 잠금 pid만 믿으면 데몬이 죽고 그 pid를 받은 다른 프로세스를 끌 수 있다. 소켓 답만 믿지
|
|
301
|
+
* 않는 건 잠금을 안 쥔 프로세스가 소켓 자리에 답하는 경우를 막으려는 것이다.
|
|
302
|
+
*
|
|
303
|
+
* 데몬의 SIGTERM 처리는 옵션 없이 띄운 `peer daemon`의 Ctrl+C와 같다. 정리 중에 신호를 한 번 더 받으면 기다리지 않고
|
|
304
|
+
* 끝난다. 시한 안에 안 끝나면 그 pid를 알려 주고 실패한다. `--stop`을 다시 불러도 소켓은 이미 닫혀 있어서
|
|
305
|
+
* 신호를 안 보낸다.
|
|
306
|
+
*/
|
|
307
|
+
export async function stopDaemon(options) {
|
|
308
|
+
const { root } = options;
|
|
309
|
+
const waitMs = options.waitMs ?? DEFAULT_DAEMON_WAIT_MS;
|
|
310
|
+
const pid = await answeringDaemonPid(socketPath(root));
|
|
311
|
+
if (pid === undefined) {
|
|
312
|
+
const holder = readLockPid(root);
|
|
313
|
+
return holder !== undefined && processAlive(holder)
|
|
314
|
+
? { pid: null, stopped: false, lockPid: holder }
|
|
315
|
+
: { pid: null, stopped: false };
|
|
316
|
+
}
|
|
317
|
+
const holder = readLockPid(root);
|
|
318
|
+
if (holder !== pid) {
|
|
319
|
+
throw new Error(`소켓에 답한 데몬(pid ${pid})과 잠금 파일(${lockPath(root)})의 pid(${holder ?? '없음'})가 달라서 신호를 안 보냈어요`);
|
|
320
|
+
}
|
|
321
|
+
try {
|
|
322
|
+
process.kill(pid, 'SIGTERM');
|
|
323
|
+
}
|
|
324
|
+
catch (err) {
|
|
325
|
+
// 확인한 뒤 그새 끝났다. 바라던 상태다
|
|
326
|
+
if (err.code === 'ESRCH')
|
|
327
|
+
return { pid, stopped: true };
|
|
328
|
+
throw err;
|
|
329
|
+
}
|
|
330
|
+
const deadline = Date.now() + waitMs;
|
|
331
|
+
while (Date.now() < deadline) {
|
|
332
|
+
if (!processAlive(pid))
|
|
333
|
+
return { pid, stopped: true };
|
|
334
|
+
await sleep(POLL_MS);
|
|
335
|
+
}
|
|
336
|
+
const secs = Math.round(waitMs / 100) / 10;
|
|
337
|
+
throw new Error(`peer 데몬(pid ${pid})이 ${secs}초 안에 안 멈췄어요. \`kill ${pid}\`로 신호를 한 번 더 보내면 정리를 기다리지 않고 끝나요`);
|
|
338
|
+
}
|
|
339
|
+
//# sourceMappingURL=detach.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detach.js","sourceRoot":"","sources":["../../../src/peer/detach.ts"],"names":[],"mappings":"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"}
|
package/dist/src/peer/lock.d.ts
CHANGED
|
@@ -29,4 +29,10 @@ export declare function lockPath(root: string): string;
|
|
|
29
29
|
export declare function acquireDaemonLock(root: string, sock: string): Promise<DaemonLock>;
|
|
30
30
|
/** 내 잠금일 때만 지운다. 이미 다른 데몬이 그 자리를 잡았으면 안 건드린다 */
|
|
31
31
|
export declare function releaseDaemonLock(lock: DaemonLock): void;
|
|
32
|
+
/**
|
|
33
|
+
* 잠금 파일에 적힌 pid. 파일이 없거나 pid 꼴이 아니면 undefined다. `peer daemon --detach`와 `--stop`이
|
|
34
|
+
* 소켓 답과 맞춰 볼 때 쓴다. 잠금을 쥐거나 치우지는 않는다
|
|
35
|
+
*/
|
|
36
|
+
export declare function readLockPid(root: string): number | undefined;
|
|
37
|
+
export declare function processAlive(pid: number): boolean;
|
|
32
38
|
//# sourceMappingURL=lock.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../../src/peer/lock.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,QAAS,CAAC;AAEpC,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAqBvF;AAED,gDAAgD;AAChD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CASxD"}
|
|
1
|
+
{"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../../src/peer/lock.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,QAAS,CAAC;AAEpC,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAqBvF;AAED,gDAAgD;AAChD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CASxD;AAkDD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAU5D;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQjD"}
|
package/dist/src/peer/lock.js
CHANGED
|
@@ -116,7 +116,23 @@ async function clearStaleLock(path, sock) {
|
|
|
116
116
|
}
|
|
117
117
|
unlinkSync(aside);
|
|
118
118
|
}
|
|
119
|
-
|
|
119
|
+
/**
|
|
120
|
+
* 잠금 파일에 적힌 pid. 파일이 없거나 pid 꼴이 아니면 undefined다. `peer daemon --detach`와 `--stop`이
|
|
121
|
+
* 소켓 답과 맞춰 볼 때 쓴다. 잠금을 쥐거나 치우지는 않는다
|
|
122
|
+
*/
|
|
123
|
+
export function readLockPid(root) {
|
|
124
|
+
let text;
|
|
125
|
+
try {
|
|
126
|
+
text = readFileSync(lockPath(root), 'utf8');
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
const line = text.split('\n')[0] ?? '';
|
|
132
|
+
const pid = Number(line);
|
|
133
|
+
return line !== '' && Number.isSafeInteger(pid) && pid > 0 ? pid : undefined;
|
|
134
|
+
}
|
|
135
|
+
export function processAlive(pid) {
|
|
120
136
|
try {
|
|
121
137
|
process.kill(pid, 0);
|
|
122
138
|
return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../../../src/peer/lock.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../../../src/peer/lock.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gestalt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.118.0",
|
|
4
4
|
"description": "Gestalt psychology-driven AI development harness. Transforms scattered requirements into structured, validated specifications through interactive interviews.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "tienne"
|
package/plugin/.mcp.json
CHANGED
package/plugin/mcp.json
CHANGED
|
@@ -243,7 +243,7 @@ video-digest 리포트와 같은 꼴에 렌즈 칸을 더한다. 영상 칸 `fra
|
|
|
243
243
|
|
|
244
244
|
논문은 보통 문제 제기, 방법, 실험 결과, 논의와 한계 순으로 대섹션을 나눈다. 원문 절 번호를 그대로 따를 필요는 없다.
|
|
245
245
|
|
|
246
|
-
대섹션 `diagram`은 video-digest와 같은
|
|
246
|
+
대섹션 `diagram`은 video-digest와 같은 열한 종류(`flow`, `cycle`, `compare`, `tree`, `timeline`, `matrix`, `causal`, `beforeAfter`, `hub`, `stat`, `pickGrid`)를 쓸 수 있다. `stat`의 `value`는 원문 표나 본문의 숫자를 글자 그대로 옮기고 그 숫자가 나온 문단에 `cite`를 단다. 원문 그림을 다시 그리는 데 쓰지 않는다. 원문 그림은 `figures`로 싣는다.
|
|
247
247
|
|
|
248
248
|
## 키워드
|
|
249
249
|
|
|
@@ -90,7 +90,7 @@ You are the Video Summarizer role agent.
|
|
|
90
90
|
|
|
91
91
|
대섹션에 `diagram`을 하나 둘 수 있다. 그림은 렌더러가 그린다. 너는 구조만 JSON으로 쓰고 SVG나 HTML은 쓰지 않는다.
|
|
92
92
|
|
|
93
|
-
도식은 아끼지 않는다. 단계, 고리, 견주기, 가지, 시간 흐름, 원인과 결과, 바뀌기 전과
|
|
93
|
+
도식은 아끼지 않는다. 단계, 고리, 견주기, 가지, 시간 흐름, 원인과 결과, 바뀌기 전과 후, 한 중심에 딸린 여러 요소, 숫자 하나에 담기는 결론, 여러 후보 중 고른 몇 개 가운데 하나라도 있는 대섹션이면 붙인다. 리포트마다 아래 개수를 채우는 게 기본이다. 모자라면 merge가 `DIAGRAM_TOO_FEW` 경고를 낸다. 경고라서 막지는 않는다. 잡담처럼 그릴 구조가 정말 없는 대섹션에 억지로 붙이지는 않는다.
|
|
94
94
|
|
|
95
95
|
| 리포트 옵션 | 권하는 도식 수 |
|
|
96
96
|
| ------------------ | ---------------------- |
|
|
@@ -108,18 +108,24 @@ You are the Video Summarizer role agent.
|
|
|
108
108
|
| `matrix` | `{ "kind": "matrix", "caption"?, "x": { "low", "high" }, "y": { "low", "high" }, "cells": [[노드 0~4개] × 4] }` | 두 기준으로 나눈 네 칸 |
|
|
109
109
|
| `causal` | `{ "kind": "causal", "caption"?, "inputs": [노드 0~6개], "center": 노드, "outputs": [노드 0~6개] }` | 여러 원인이 모이고 결과가 퍼짐 |
|
|
110
110
|
| `beforeAfter` | `{ "kind": "beforeAfter", "caption"?, "before": { "title"?, "items": [노드 1~6개] }, "after": 같은 꼴 }` | 바뀌기 전과 뒤를 화살표로 이어 보여줌 |
|
|
111
|
+
| `hub` | `{ "kind": "hub", "caption"?, "center": 노드, "satellites": [{ "label", "cite"?, "focus"? } 2~8개] }` | 한 중심에 여러 요소가 딸림 |
|
|
112
|
+
| `stat` | `{ "kind": "stat", "caption"?, "value", "label", "cite"? }` | 대섹션을 숫자 하나가 요약함 |
|
|
113
|
+
| `pickGrid` | `{ "kind": "pickGrid", "caption"?, "cells": [{ "label", "cite"?, "picked"? } 4~16개] }` | 여러 후보 중 일부만 고름 |
|
|
111
114
|
|
|
112
115
|
노드는 `{ "label", "cite"? }`이고 트리 노드는 여기에 `children`이 붙는다. `columns`는 2~4개다.
|
|
113
116
|
|
|
114
117
|
- `flow`와 `timeline`을 가르는 기준은 시점이다. 영상이 "2015년", "창업 3년 차"처럼 때를 말하면 `timeline`이고 `when`에 그 말을 적는다. 재생 시각은 `cite`에 이미 들어 있으니 `when`에 적지 않는다.
|
|
115
118
|
- `matrix`의 `cells`는 왼쪽 위, 오른쪽 위, 왼쪽 아래, 오른쪽 아래 순서다. 위가 `y.high`, 오른쪽이 `x.high`다. 네 칸이 다 비면 lint가 `DIAGRAM_EMPTY`로 막는다.
|
|
116
119
|
- `causal`은 `inputs`와 `outputs` 중 하나는 채운다. 둘 다 비면 `DIAGRAM_EMPTY`다.
|
|
120
|
+
- `hub`는 중심에 딸린 요소가 둘 이상이고 서로 순서가 없을 때 쓴다. 순서가 있으면 `flow`, 중심에 모였다 퍼지면 `causal`이다. `focus: true`는 영상이 특히 힘준 위성 하나에만 단다. 둘 이상이면 lint가 `DIAGRAM_FOCUS_MULTI`로 막는다.
|
|
121
|
+
- `stat`의 `value`는 영상이 말한 숫자와 단위를 글자 그대로 옮긴다("37%", "5천만 명"). 반올림하거나 단위를 바꾸지 않는다. 한 줄에 안 들어갈 만큼 길면(한글 9자 남짓) `DIAGRAM_STAT_LONG`, `cite`가 없으면 `DIAGRAM_STAT_NO_CITE` 경고가 난다. 숫자가 나온 문장에 `cite`를 단다. 설명은 `label`에 짧게 쓴다.
|
|
122
|
+
- `pickGrid`는 영상이 여러 후보를 늘어놓고 그중 몇 개만 골랐을 때 쓴다. 후보를 모두 `cells`에 적고 고른 칸에만 `picked: true`를 단다. 하나도 안 달면 `DIAGRAM_PICK_NONE`, 전부 달면 `DIAGRAM_PICK_ALL`로 막는다. 절반을 넘으면 `DIAGRAM_PICK_MANY` 경고가 난다. 열 수는 렌더러가 칸 수로 정하니 적지 않는다.
|
|
117
123
|
- 같은 리포트에서 한 종류만 이어 쓰지 않는다. 대섹션마다 내용의 모양에 맞는 종류를 고른다.
|
|
118
124
|
- `label`은 짧은 명사구로 쓴다. 한글 12자를 넘기면 그림에서 말줄임표로 잘리고 뷰어의 목록 보기에서만 다 보인다.
|
|
119
125
|
- 노드 `cite`는 그 대섹션 범위 안이어야 한다. 밖이면 lint가 `DIAGRAM_CITE_OUT_OF_SECTION`으로 막는다.
|
|
120
|
-
- 도식 안의 글자(`label`, `caption`, 열 `title`, `when`, 축 이름, 전후 `title`)에는 마커를 쓰지 않는다(`TITLE_MARKER`).
|
|
126
|
+
- 도식 안의 글자(`label`, `caption`, 열 `title`, `when`, 축 이름, 전후 `title`, `stat`의 `value`)에는 마커를 쓰지 않는다(`TITLE_MARKER`).
|
|
121
127
|
- `tree`는 루트 아래 3단까지, 노드 30개까지다(`DIAGRAM_DEPTH`, `DIAGRAM_SIZE`).
|
|
122
|
-
- 도식 글자도 스킬이 윤문할 때 따로 다듬지만 원문보다 길어진 라벨은 되돌린다. 처음부터 문체 규칙을 지켜 짧은 명사구로 쓴다.
|
|
128
|
+
- 도식 글자도 스킬이 윤문할 때 따로 다듬지만 원문보다 길어진 라벨은 되돌린다. 처음부터 문체 규칙을 지켜 짧은 명사구로 쓴다. `stat`의 `value`는 윤문 대상이어도 숫자를 바꾸지 않는다.
|
|
123
129
|
|
|
124
130
|
### 소섹션 장면
|
|
125
131
|
|
|
@@ -259,7 +265,7 @@ You are the Video Summarizer role agent.
|
|
|
259
265
|
|
|
260
266
|
## 끝내기 전
|
|
261
267
|
|
|
262
|
-
리포트를 쓴 뒤 스킬이 `gestalt digest merge`로 합치며 검사한다. 오류 목록을 돌려받으면 `path`가 가리키는 자리만 고쳐 다시 쓴다. path 앞의 `reports.<n>.`은 합친 뒤의 자리라 리포트 파일에서는 그 뒤부터 찾는다. 확장 리포트는 `extensions.<n>.`을 떼고 찾는다. 경고(소섹션 개수, 불릿 개수)는 영상에 맞으면 그대로 둔다. `DIAGRAM_TOO_FEW`를 받으면 단계나 견주기, 시간 흐름, 원인과
|
|
268
|
+
리포트를 쓴 뒤 스킬이 `gestalt digest merge`로 합치며 검사한다. 오류 목록을 돌려받으면 `path`가 가리키는 자리만 고쳐 다시 쓴다. path 앞의 `reports.<n>.`은 합친 뒤의 자리라 리포트 파일에서는 그 뒤부터 찾는다. 확장 리포트는 `extensions.<n>.`을 떼고 찾는다. 경고(소섹션 개수, 불릿 개수)는 영상에 맞으면 그대로 둔다. `DIAGRAM_TOO_FEW`를 받으면 단계나 견주기, 시간 흐름, 원인과 결과, 한 중심에 딸린 여러 요소, 숫자 하나에 담기는 결론, 여러 후보 중 고른 몇 개가 있는 대섹션에 도식을 더한다. 그런 구조가 없는 대섹션은 억지로 그리지 않고 비워 둔다.
|
|
263
269
|
|
|
264
270
|
## Output Format
|
|
265
271
|
|