@tienne/gestalt 0.111.0 → 0.113.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 (166) hide show
  1. package/CLAUDE.md +3 -3
  2. package/README.ko.md +1 -1
  3. package/README.md +1 -1
  4. package/dist/package.json +3 -1
  5. package/dist/plugin/role-agents/lens-context/AGENT.md +8 -7
  6. package/dist/plugin/role-agents/lens-reader/AGENT.md +48 -2
  7. package/dist/plugin/skills/lens/SKILL.md +22 -15
  8. package/dist/src/architecture/doc-fresh.d.ts.map +1 -1
  9. package/dist/src/architecture/doc-fresh.js +3 -1
  10. package/dist/src/architecture/doc-fresh.js.map +1 -1
  11. package/dist/src/cli/commands/lens.d.ts +8 -1
  12. package/dist/src/cli/commands/lens.d.ts.map +1 -1
  13. package/dist/src/cli/commands/lens.js +29 -2
  14. package/dist/src/cli/commands/lens.js.map +1 -1
  15. package/dist/src/cli/commands/peer.d.ts +20 -0
  16. package/dist/src/cli/commands/peer.d.ts.map +1 -1
  17. package/dist/src/cli/commands/peer.js +198 -12
  18. package/dist/src/cli/commands/peer.js.map +1 -1
  19. package/dist/src/cli/index.d.ts.map +1 -1
  20. package/dist/src/cli/index.js +44 -4
  21. package/dist/src/cli/index.js.map +1 -1
  22. package/dist/src/digest/lens-schema.d.ts +150 -3
  23. package/dist/src/digest/lens-schema.d.ts.map +1 -1
  24. package/dist/src/digest/lens-schema.js +14 -1
  25. package/dist/src/digest/lens-schema.js.map +1 -1
  26. package/dist/src/digest/lens-widget-schema.d.ts +2 -2
  27. package/dist/src/digest/lint-lens.d.ts +2 -1
  28. package/dist/src/digest/lint-lens.d.ts.map +1 -1
  29. package/dist/src/digest/lint-lens.js +68 -7
  30. package/dist/src/digest/lint-lens.js.map +1 -1
  31. package/dist/src/digest/ocr.d.ts +1 -1
  32. package/dist/src/digest/ocr.d.ts.map +1 -1
  33. package/dist/src/digest/ocr.js +10 -4
  34. package/dist/src/digest/ocr.js.map +1 -1
  35. package/dist/src/digest/schema.d.ts +62 -62
  36. package/dist/src/lens/attach.d.ts +741 -0
  37. package/dist/src/lens/attach.d.ts.map +1 -1
  38. package/dist/src/lens/attach.js +41 -11
  39. package/dist/src/lens/attach.js.map +1 -1
  40. package/dist/src/lens/context-input.d.ts +17 -0
  41. package/dist/src/lens/context-input.d.ts.map +1 -0
  42. package/dist/src/lens/context-input.js +31 -0
  43. package/dist/src/lens/context-input.js.map +1 -0
  44. package/dist/src/lens/ingest.d.ts +19 -1
  45. package/dist/src/lens/ingest.d.ts.map +1 -1
  46. package/dist/src/lens/ingest.js +92 -14
  47. package/dist/src/lens/ingest.js.map +1 -1
  48. package/dist/src/lens/pdf-extract-py.d.ts +2 -0
  49. package/dist/src/lens/pdf-extract-py.d.ts.map +1 -1
  50. package/dist/src/lens/pdf-extract-py.js +37 -2
  51. package/dist/src/lens/pdf-extract-py.js.map +1 -1
  52. package/dist/src/mcp/schemas.d.ts +29 -0
  53. package/dist/src/mcp/schemas.d.ts.map +1 -1
  54. package/dist/src/mcp/schemas.js +29 -0
  55. package/dist/src/mcp/schemas.js.map +1 -1
  56. package/dist/src/mcp/server.d.ts.map +1 -1
  57. package/dist/src/mcp/server.js +6 -1
  58. package/dist/src/mcp/server.js.map +1 -1
  59. package/dist/src/mcp/tools/architecture-passthrough.d.ts.map +1 -1
  60. package/dist/src/mcp/tools/architecture-passthrough.js +1 -1
  61. package/dist/src/mcp/tools/architecture-passthrough.js.map +1 -1
  62. package/dist/src/mcp/tools/peer.d.ts +24 -0
  63. package/dist/src/mcp/tools/peer.d.ts.map +1 -0
  64. package/dist/src/mcp/tools/peer.js +103 -0
  65. package/dist/src/mcp/tools/peer.js.map +1 -0
  66. package/dist/src/peer/codex.d.ts +57 -0
  67. package/dist/src/peer/codex.d.ts.map +1 -0
  68. package/dist/src/peer/codex.js +303 -0
  69. package/dist/src/peer/codex.js.map +1 -0
  70. package/dist/src/peer/daemon.d.ts +76 -1
  71. package/dist/src/peer/daemon.d.ts.map +1 -1
  72. package/dist/src/peer/daemon.js +511 -19
  73. package/dist/src/peer/daemon.js.map +1 -1
  74. package/dist/src/peer/errors.d.ts +3 -0
  75. package/dist/src/peer/errors.d.ts.map +1 -1
  76. package/dist/src/peer/errors.js +3 -0
  77. package/dist/src/peer/errors.js.map +1 -1
  78. package/dist/src/peer/excerpt.d.ts +47 -0
  79. package/dist/src/peer/excerpt.d.ts.map +1 -0
  80. package/dist/src/peer/excerpt.js +160 -0
  81. package/dist/src/peer/excerpt.js.map +1 -0
  82. package/dist/src/peer/feed.d.ts +35 -2
  83. package/dist/src/peer/feed.d.ts.map +1 -1
  84. package/dist/src/peer/feed.js +22 -0
  85. package/dist/src/peer/feed.js.map +1 -1
  86. package/dist/src/peer/inbox.d.ts +42 -0
  87. package/dist/src/peer/inbox.d.ts.map +1 -0
  88. package/dist/src/peer/inbox.js +96 -0
  89. package/dist/src/peer/inbox.js.map +1 -0
  90. package/dist/src/peer/locate.d.ts +5 -0
  91. package/dist/src/peer/locate.d.ts.map +1 -1
  92. package/dist/src/peer/locate.js +19 -2
  93. package/dist/src/peer/locate.js.map +1 -1
  94. package/dist/src/peer/message.d.ts +113 -0
  95. package/dist/src/peer/message.d.ts.map +1 -0
  96. package/dist/src/peer/message.js +183 -0
  97. package/dist/src/peer/message.js.map +1 -0
  98. package/dist/src/peer/mirror.d.ts +50 -1
  99. package/dist/src/peer/mirror.d.ts.map +1 -1
  100. package/dist/src/peer/mirror.js +138 -0
  101. package/dist/src/peer/mirror.js.map +1 -1
  102. package/dist/src/peer/network.d.ts +229 -1
  103. package/dist/src/peer/network.d.ts.map +1 -1
  104. package/dist/src/peer/network.js +867 -44
  105. package/dist/src/peer/network.js.map +1 -1
  106. package/dist/src/peer/paths.d.ts +6 -0
  107. package/dist/src/peer/paths.d.ts.map +1 -1
  108. package/dist/src/peer/paths.js +8 -0
  109. package/dist/src/peer/paths.js.map +1 -1
  110. package/dist/src/peer/peek.d.ts +79 -0
  111. package/dist/src/peer/peek.d.ts.map +1 -0
  112. package/dist/src/peer/peek.js +465 -0
  113. package/dist/src/peer/peek.js.map +1 -0
  114. package/dist/src/peer/peeks.d.ts +115 -0
  115. package/dist/src/peer/peeks.d.ts.map +1 -0
  116. package/dist/src/peer/peeks.js +262 -0
  117. package/dist/src/peer/peeks.js.map +1 -0
  118. package/dist/src/peer/protocol.d.ts +128 -4
  119. package/dist/src/peer/protocol.d.ts.map +1 -1
  120. package/dist/src/peer/protocol.js.map +1 -1
  121. package/dist/src/peer/questions.d.ts +168 -0
  122. package/dist/src/peer/questions.d.ts.map +1 -0
  123. package/dist/src/peer/questions.js +389 -0
  124. package/dist/src/peer/questions.js.map +1 -0
  125. package/dist/src/peer/relay.d.ts +14 -0
  126. package/dist/src/peer/relay.d.ts.map +1 -1
  127. package/dist/src/peer/relay.js +102 -7
  128. package/dist/src/peer/relay.js.map +1 -1
  129. package/dist/src/peer/roster.d.ts +2 -0
  130. package/dist/src/peer/roster.d.ts.map +1 -1
  131. package/dist/src/peer/roster.js +5 -0
  132. package/dist/src/peer/roster.js.map +1 -1
  133. package/dist/src/peer/share.d.ts +48 -1
  134. package/dist/src/peer/share.d.ts.map +1 -1
  135. package/dist/src/peer/share.js +167 -2
  136. package/dist/src/peer/share.js.map +1 -1
  137. package/dist/src/peer/state.d.ts +12 -1
  138. package/dist/src/peer/state.d.ts.map +1 -1
  139. package/dist/src/peer/state.js +15 -0
  140. package/dist/src/peer/state.js.map +1 -1
  141. package/dist/src/peer/transform.d.ts +32 -0
  142. package/dist/src/peer/transform.d.ts.map +1 -1
  143. package/dist/src/peer/transform.js +52 -33
  144. package/dist/src/peer/transform.js.map +1 -1
  145. package/dist/src/peer/transport.d.ts +7 -3
  146. package/dist/src/peer/transport.d.ts.map +1 -1
  147. package/dist/src/peer/transport.js +12 -4
  148. package/dist/src/peer/transport.js.map +1 -1
  149. package/dist/src/peer/viewer-html.d.ts +13 -1
  150. package/dist/src/peer/viewer-html.d.ts.map +1 -1
  151. package/dist/src/peer/viewer-html.js +328 -4
  152. package/dist/src/peer/viewer-html.js.map +1 -1
  153. package/dist/src/peer/viewer.d.ts +49 -1
  154. package/dist/src/peer/viewer.d.ts.map +1 -1
  155. package/dist/src/peer/viewer.js +133 -7
  156. package/dist/src/peer/viewer.js.map +1 -1
  157. package/dist/src/peer/wire.d.ts +9 -2
  158. package/dist/src/peer/wire.d.ts.map +1 -1
  159. package/dist/src/peer/wire.js.map +1 -1
  160. package/package.json +3 -1
  161. package/plugin/.codex-plugin/plugin.json +1 -1
  162. package/plugin/.mcp.json +1 -1
  163. package/plugin/mcp.json +1 -1
  164. package/plugin/role-agents/lens-context/AGENT.md +8 -7
  165. package/plugin/role-agents/lens-reader/AGENT.md +48 -2
  166. package/plugin/skills/lens/SKILL.md +22 -15
@@ -0,0 +1,103 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { request } from '../../peer/client.js';
3
+ import { errMessage } from '../../peer/errors.js';
4
+ import { claudeConfigDir, findSessionByPid } from '../../peer/locate.js';
5
+ import { peerRoot, socketPath } from '../../peer/paths.js';
6
+ /**
7
+ * 세션을 찾을 pid 후보. 부모가 먼저고 `npx`처럼 사이에 프로세스가 하나 끼면 그 부모까지 본다.
8
+ * Claude Code가 자식에게 주는 `CLAUDE_PID`가 있으면 그걸 맨 앞에 둔다.
9
+ */
10
+ export function sessionPids(env = process.env) {
11
+ const pids = [];
12
+ const fromEnv = Number(env['CLAUDE_PID']);
13
+ if (Number.isInteger(fromEnv) && fromEnv > 0)
14
+ pids.push(fromEnv);
15
+ pids.push(process.ppid);
16
+ const grand = parentOf(process.ppid);
17
+ if (grand !== undefined)
18
+ pids.push(grand);
19
+ return [...new Set(pids)];
20
+ }
21
+ function parentOf(pid) {
22
+ try {
23
+ const out = execFileSync('ps', ['-o', 'ppid=', '-p', String(pid)], {
24
+ encoding: 'utf8',
25
+ stdio: ['ignore', 'pipe', 'ignore'],
26
+ timeout: 2_000,
27
+ });
28
+ const n = Number(out.trim());
29
+ return Number.isInteger(n) && n > 1 ? n : undefined;
30
+ }
31
+ catch {
32
+ return undefined;
33
+ }
34
+ }
35
+ export async function handlePeer(input, deps = {}) {
36
+ if (input.action === 'peek')
37
+ return handlePeek(input, deps);
38
+ if (input.question === undefined)
39
+ return JSON.stringify({ error: 'ask_user는 question이 필요해요' });
40
+ const configDir = deps.configDir ?? claudeConfigDir();
41
+ const pids = deps.pids ?? sessionPids();
42
+ const session = pids.map((pid) => findSessionByPid(pid, configDir)).find((s) => s !== null);
43
+ if (!session) {
44
+ return JSON.stringify({
45
+ error: 'Claude Code 세션 안에서만 쓸 수 있어요. 이 MCP 서버의 부모 세션을 못 찾았어요',
46
+ configDir,
47
+ });
48
+ }
49
+ let sock;
50
+ try {
51
+ sock = deps.socket ?? socketPath(peerRoot());
52
+ }
53
+ catch (err) {
54
+ return JSON.stringify({ error: errMessage(err) });
55
+ }
56
+ try {
57
+ const res = await request(sock, {
58
+ op: 'ask',
59
+ sessionId: session.sessionId,
60
+ question: input.question,
61
+ ...(input.to !== undefined ? { to: input.to } : {}),
62
+ ...(input.timeoutSecs !== undefined ? { timeoutSecs: input.timeoutSecs } : {}),
63
+ });
64
+ if (!res.ok)
65
+ return JSON.stringify({ error: res.error });
66
+ return JSON.stringify({
67
+ ...res.result,
68
+ note: '질문을 보냈다. 답은 기다리지 말고 하던 일을 이어 간다. 답은 <peer-answer from=… question=… verified> 메시지로 이 세션에 들어온다. expiresAt이 지나면 더 안 온다.',
69
+ });
70
+ }
71
+ catch (err) {
72
+ return JSON.stringify({ error: errMessage(err) });
73
+ }
74
+ }
75
+ async function handlePeek(input, deps) {
76
+ if (input.share === undefined) {
77
+ return JSON.stringify({
78
+ error: 'peek은 share가 필요해요. 링크의 공유 id나 사용자가 알려 준 공유 id를 넣어 주세요',
79
+ });
80
+ }
81
+ let sock;
82
+ try {
83
+ sock = deps.socket ?? socketPath(peerRoot());
84
+ }
85
+ catch (err) {
86
+ return JSON.stringify({ error: errMessage(err) });
87
+ }
88
+ try {
89
+ // 주인 데몬이 답하길 기다린다. 데몬 쪽 시한(10초)보다 넉넉하게 둔다
90
+ const res = await request(sock, {
91
+ op: 'peek',
92
+ share: input.share,
93
+ ...(input.since !== undefined ? { since: input.since } : {}),
94
+ }, 15_000);
95
+ if (!res.ok)
96
+ return JSON.stringify({ error: res.error });
97
+ return res.result.text;
98
+ }
99
+ catch (err) {
100
+ return JSON.stringify({ error: errMessage(err) });
101
+ }
102
+ }
103
+ //# sourceMappingURL=peer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peer.js","sourceRoot":"","sources":["../../../../src/mcp/tools/peer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import type { PeerEvent, TransformOptions } from './transform.js';
2
+ /**
3
+ * Codex 대화 기록(rollout) 읽기. codex-cli 0.147.0 exec 기록으로 확인한 형식이다. 허용 목록 가운데
4
+ * function_call, local_shell_call, function_call_output은 기록에 없어서 바이너리에 있는 이름을 따랐고
5
+ * 필드는 추정이다.
6
+ *
7
+ * 기록은 `$CODEX_HOME/sessions/<연>/<월>/<일>/rollout-<시각>-<thread id>.jsonl`에 남는다.
8
+ * `state_5.sqlite`의 threads 테이블은 이 경로를 가리키는 색인이고 본문은 jsonl에만 있다.
9
+ * 줄은 모두 `{timestamp, type, payload}`다. 문서화되지 않은 형식이라 허용 목록에 있는 것만 꺼낸다.
10
+ */
11
+ /** Codex 설정 디렉토리. 오르카처럼 `CODEX_HOME`으로 옮겨 둔 경우가 있다 */
12
+ export declare function codexHome(env?: NodeJS.ProcessEnv): string;
13
+ export type CodexLocateResult = {
14
+ ok: true;
15
+ path: string;
16
+ home: string;
17
+ } | {
18
+ ok: false;
19
+ reason: string;
20
+ home: string;
21
+ };
22
+ /**
23
+ * `--codex`에 준 값으로 rollout 파일을 찾는다. `.jsonl`로 끝나면 경로로 보고 아니면 thread id로
24
+ * `sessions/` 아래에서 파일 이름이 `-<id>.jsonl`로 끝나는 rollout을 찾는다. SQLite 색인은 안
25
+ * 읽는다. 스키마 번호가 바뀌어도 파일 이름 규칙은 그대로라 새 의존성 없이 찾을 수 있다.
26
+ */
27
+ export declare function locateCodexRollout(value: string, home?: string, cwd?: string): CodexLocateResult;
28
+ /**
29
+ * 이름이 숫자인 하위 디렉토리를 큰 것부터. 연, 월, 일 디렉토리가 이 꼴이다. 숫자가 아닌 하위 디렉토리나
30
+ * rollout 꼴 파일이 있었으면 odd다. `.DS_Store` 같은 다른 파일은 날짜 규칙이 바뀐 신호가 아니라 안 센다
31
+ */
32
+ export declare function subdirs(dir: string): {
33
+ dirs: string[];
34
+ odd: boolean;
35
+ };
36
+ /**
37
+ * Codex rollout 한 줄씩 받아 허용 목록에 있는 것만 `PeerEvent`로 바꾼다. Claude Code 기록의
38
+ * TranscriptTransformer와 같은 자리에 끼우고 가리기도 같은 규칙을 탄다.
39
+ */
40
+ export declare class CodexTransformer {
41
+ private readonly options;
42
+ private unknown;
43
+ private failed;
44
+ private cliVersion;
45
+ constructor(options: TransformOptions);
46
+ get unknownLines(): number;
47
+ get failedLines(): number;
48
+ /** 마지막으로 본 codex-cli 버전. 모르는 줄이 생겼을 때 감사 로그에 남긴다 */
49
+ get version(): string | undefined;
50
+ push(line: string): PeerEvent[];
51
+ private parse;
52
+ private fromEvent;
53
+ private fromItem;
54
+ private call;
55
+ private redact;
56
+ }
57
+ //# sourceMappingURL=codex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../../src/peer/codex.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGlE;;;;;;;;GAQG;AAEH,sDAAsD;AACtD,wBAAgB,SAAS,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAItE;AAKD,MAAM,MAAM,iBAAiB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,IAAI,SAAc,EAClB,GAAG,SAAgB,GAClB,iBAAiB,CAwDnB;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,CAYrE;AA4DD;;;GAGG;AACH,qBAAa,gBAAgB;IAKf,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,UAAU,CAAqB;gBAEV,OAAO,EAAE,gBAAgB;IAEtD,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,oDAAoD;IACpD,IAAI,OAAO,IAAI,MAAM,GAAG,SAAS,CAEhC;IAED,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE;IAS/B,OAAO,CAAC,KAAK;IA2Bb,OAAO,CAAC,SAAS;IAajB,OAAO,CAAC,QAAQ;IA0BhB,OAAO,CAAC,IAAI;IAKZ,OAAO,CAAC,MAAM;CAGf"}
@@ -0,0 +1,303 @@
1
+ import { readdirSync, statSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { basename, isAbsolute, join, resolve } from 'node:path';
4
+ import { redactText } from './redact.js';
5
+ import { isRecord, toolCallEvent, toolResultEvent } from './transform.js';
6
+ /**
7
+ * Codex 대화 기록(rollout) 읽기. codex-cli 0.147.0 exec 기록으로 확인한 형식이다. 허용 목록 가운데
8
+ * function_call, local_shell_call, function_call_output은 기록에 없어서 바이너리에 있는 이름을 따랐고
9
+ * 필드는 추정이다.
10
+ *
11
+ * 기록은 `$CODEX_HOME/sessions/<연>/<월>/<일>/rollout-<시각>-<thread id>.jsonl`에 남는다.
12
+ * `state_5.sqlite`의 threads 테이블은 이 경로를 가리키는 색인이고 본문은 jsonl에만 있다.
13
+ * 줄은 모두 `{timestamp, type, payload}`다. 문서화되지 않은 형식이라 허용 목록에 있는 것만 꺼낸다.
14
+ */
15
+ /** Codex 설정 디렉토리. 오르카처럼 `CODEX_HOME`으로 옮겨 둔 경우가 있다 */
16
+ export function codexHome(env = process.env) {
17
+ const raw = env['CODEX_HOME'];
18
+ if (raw && isAbsolute(raw))
19
+ return raw;
20
+ return join(homedir(), '.codex');
21
+ }
22
+ /** thread id. 파일 이름 조각으로 쓰이므로 `..`이나 `/`가 들어오면 안 된다 */
23
+ const THREAD_ID = /^[A-Za-z0-9][A-Za-z0-9-]{7,63}$/;
24
+ /**
25
+ * `--codex`에 준 값으로 rollout 파일을 찾는다. `.jsonl`로 끝나면 경로로 보고 아니면 thread id로
26
+ * `sessions/` 아래에서 파일 이름이 `-<id>.jsonl`로 끝나는 rollout을 찾는다. SQLite 색인은 안
27
+ * 읽는다. 스키마 번호가 바뀌어도 파일 이름 규칙은 그대로라 새 의존성 없이 찾을 수 있다.
28
+ */
29
+ export function locateCodexRollout(value, home = codexHome(), cwd = process.cwd()) {
30
+ if (value.endsWith('.jsonl')) {
31
+ const path = isAbsolute(value) ? value : resolve(cwd, value);
32
+ return isFile(path)
33
+ ? { ok: true, path, home }
34
+ : { ok: false, reason: `rollout 파일이 없어요: ${path}`, home };
35
+ }
36
+ if (!THREAD_ID.test(value)) {
37
+ return { ok: false, reason: 'thread id나 rollout 경로(.jsonl)를 주세요', home };
38
+ }
39
+ const root = join(home, 'sessions');
40
+ if (!isDir(root))
41
+ return { ok: false, reason: 'sessions 디렉토리를 못 읽었어요', home };
42
+ const suffix = `-${value}.jsonl`;
43
+ const pick = (dir, names) => {
44
+ const hits = names
45
+ .filter((n) => basename(n).startsWith('rollout-') && n.endsWith(suffix))
46
+ .map((n) => join(dir, n))
47
+ .filter(isFile);
48
+ // 같은 날 같은 id가 둘이면 이름이 뒤인(나중에 만든) 것을 쓴다. 파일 이름이 시각으로 시작한다
49
+ return hits.sort().at(-1);
50
+ };
51
+ // 연/월/일 디렉토리를 최신순으로 내려가다 처음 찾은 날에서 멈춘다. 보통 공유하는 건 최근 세션이다.
52
+ // 날짜 꼴이 아닌 자리(연, 월 디렉토리의 다른 이름 디렉토리나 rollout 파일, 일 디렉토리 안의 하위
53
+ // 디렉토리)를 봤으면 표시해 둔다
54
+ let odd = false;
55
+ const days = (dir) => {
56
+ const r = subdirs(dir);
57
+ if (r.odd)
58
+ odd = true;
59
+ return r.dirs;
60
+ };
61
+ for (const year of days(root)) {
62
+ for (const month of days(join(root, year))) {
63
+ for (const day of days(join(root, year, month))) {
64
+ const dir = join(root, year, month, day);
65
+ const entries = readEntries(dir);
66
+ if (entries.some((e) => e.isDirectory()))
67
+ odd = true;
68
+ const found = pick(dir, entries.filter((e) => !e.isDirectory()).map((e) => e.name));
69
+ if (found)
70
+ return { ok: true, path: found, home };
71
+ }
72
+ }
73
+ }
74
+ // 날짜 꼴이 아닌 자리가 있었을 때만 전체를 훑는다. 디렉토리 규칙이 바뀌어도 못 찾는 일은 없게 두되
75
+ // 날짜 디렉토리뿐이면 이미 다 본 것이라 다시 훑지 않는다
76
+ if (!odd)
77
+ return { ok: false, reason: '그 id의 rollout을 못 찾았어요', home };
78
+ let names;
79
+ try {
80
+ names = readdirSync(root, { recursive: true, encoding: 'utf8' });
81
+ }
82
+ catch {
83
+ return { ok: false, reason: 'sessions 디렉토리를 못 읽었어요', home };
84
+ }
85
+ const found = pick(root, names);
86
+ if (!found)
87
+ return { ok: false, reason: '그 id의 rollout을 못 찾았어요', home };
88
+ return { ok: true, path: found, home };
89
+ }
90
+ /**
91
+ * 이름이 숫자인 하위 디렉토리를 큰 것부터. 연, 월, 일 디렉토리가 이 꼴이다. 숫자가 아닌 하위 디렉토리나
92
+ * rollout 꼴 파일이 있었으면 odd다. `.DS_Store` 같은 다른 파일은 날짜 규칙이 바뀐 신호가 아니라 안 센다
93
+ */
94
+ export function subdirs(dir) {
95
+ const entries = readEntries(dir);
96
+ const dirs = entries
97
+ .filter((d) => d.isDirectory() && /^\d+$/.test(d.name))
98
+ .map((d) => d.name)
99
+ .sort((a, b) => Number(b) - Number(a));
100
+ const odd = entries.some((d) => d.isDirectory()
101
+ ? !/^\d+$/.test(d.name)
102
+ : d.name.startsWith('rollout-') && d.name.endsWith('.jsonl'));
103
+ return { dirs, odd };
104
+ }
105
+ function readEntries(dir) {
106
+ try {
107
+ return readdirSync(dir, { withFileTypes: true });
108
+ }
109
+ catch {
110
+ return [];
111
+ }
112
+ }
113
+ function isDir(path) {
114
+ try {
115
+ return statSync(path).isDirectory();
116
+ }
117
+ catch {
118
+ return false;
119
+ }
120
+ }
121
+ function isFile(path) {
122
+ try {
123
+ return statSync(path).isFile();
124
+ }
125
+ catch {
126
+ return false;
127
+ }
128
+ }
129
+ /**
130
+ * 내용을 안 보내는 줄 종류. compacted 말고는 0.147.0 기록에서 본 것이고 compacted는 바이너리에 있는
131
+ * 이름이다. 여기 있는 건 조용히 버리고 여기에도 허용
132
+ * 목록에도 없는 종류만 "모르는 줄"로 센다. 차단 목록이 아니다 — 지워도 새는 게 없다.
133
+ *
134
+ * - session_meta: 시스템 프롬프트 원문(base_instructions)이 들어 있다
135
+ * - world_state: AGENTS.md 원문(agents_md)과 환경 정보가 들어 있다
136
+ * - turn_context: 턴마다 cwd, 권한, 모델 설정
137
+ * - compacted: 압축 요약. 지난 대화 전체를 다시 적은 글이다
138
+ */
139
+ const KNOWN_DROPPED = new Set(['session_meta', 'world_state', 'turn_context', 'compacted']);
140
+ /**
141
+ * 안 보내는 event_msg 종류. 앞의 넷은 기록에서 봤고 추론 셋은 기록에는 안 남았지만 바이너리에
142
+ * 있는 이름이다. 추론 원문은 허용 목록 밖이라 이 목록에서 빠져도 안 나간다.
143
+ */
144
+ const KNOWN_DROPPED_EVENTS = new Set([
145
+ 'task_started',
146
+ 'task_complete',
147
+ 'token_count',
148
+ 'thread_settings_applied',
149
+ 'agent_reasoning',
150
+ 'agent_reasoning_raw_content',
151
+ 'agent_reasoning_section_break',
152
+ ]);
153
+ /**
154
+ * 안 보내는 response_item 종류. message는 role과 무관하게 버린다. role user 메시지에는 사람이 친
155
+ * 말과 함께 AGENTS.md 전문과 `<environment_context>`가 들어 있고 developer 메시지는 시스템 지시다.
156
+ * 프롬프트와 답은 event_msg의 user_message, agent_message에서 꺼낸다. reasoning은 추론 원문이고 기록에
157
+ * 없어서 바이너리에 있는 이름을 넣었다.
158
+ */
159
+ const KNOWN_DROPPED_ITEMS = new Set(['message', 'reasoning']);
160
+ /**
161
+ * Codex rollout 한 줄씩 받아 허용 목록에 있는 것만 `PeerEvent`로 바꾼다. Claude Code 기록의
162
+ * TranscriptTransformer와 같은 자리에 끼우고 가리기도 같은 규칙을 탄다.
163
+ */
164
+ export class CodexTransformer {
165
+ options;
166
+ unknown = 0;
167
+ failed = 0;
168
+ cliVersion;
169
+ constructor(options) {
170
+ this.options = options;
171
+ }
172
+ get unknownLines() {
173
+ return this.unknown;
174
+ }
175
+ get failedLines() {
176
+ return this.failed;
177
+ }
178
+ /** 마지막으로 본 codex-cli 버전. 모르는 줄이 생겼을 때 감사 로그에 남긴다 */
179
+ get version() {
180
+ return this.cliVersion;
181
+ }
182
+ push(line) {
183
+ try {
184
+ return this.parse(line);
185
+ }
186
+ catch {
187
+ this.failed++;
188
+ return [];
189
+ }
190
+ }
191
+ parse(line) {
192
+ const trimmed = line.trim();
193
+ if (trimmed === '')
194
+ return [];
195
+ let parsed;
196
+ try {
197
+ parsed = JSON.parse(trimmed);
198
+ }
199
+ catch {
200
+ this.unknown++;
201
+ return [];
202
+ }
203
+ if (!isRecord(parsed) || typeof parsed['type'] !== 'string' || !isRecord(parsed['payload'])) {
204
+ this.unknown++;
205
+ return [];
206
+ }
207
+ const type = parsed['type'];
208
+ const payload = parsed['payload'];
209
+ const at = typeof parsed['timestamp'] === 'string' ? parsed['timestamp'] : undefined;
210
+ if (type === 'session_meta' && typeof payload['cli_version'] === 'string') {
211
+ this.cliVersion = payload['cli_version'];
212
+ }
213
+ if (type === 'event_msg')
214
+ return this.fromEvent(payload, at);
215
+ if (type === 'response_item')
216
+ return this.fromItem(payload, at);
217
+ if (!KNOWN_DROPPED.has(type))
218
+ this.unknown++;
219
+ return [];
220
+ }
221
+ fromEvent(payload, at) {
222
+ const kind = payload['type'];
223
+ if (kind === 'user_message' || kind === 'agent_message') {
224
+ const raw = payload['message'];
225
+ if (typeof raw !== 'string')
226
+ return [];
227
+ const text = this.redact(raw).trim();
228
+ if (text === '')
229
+ return [];
230
+ return [{ kind: kind === 'user_message' ? 'prompt' : 'reply', text, at }];
231
+ }
232
+ if (typeof kind !== 'string' || !KNOWN_DROPPED_EVENTS.has(kind))
233
+ this.unknown++;
234
+ return [];
235
+ }
236
+ fromItem(payload, at) {
237
+ const kind = payload['type'];
238
+ const callId = typeof payload['call_id'] === 'string' ? payload['call_id'] : '';
239
+ switch (kind) {
240
+ // custom_tool_call과 그 결과는 기록에서 본 꼴이다. 나머지 분기의 필드는 추정이라 꼴이 다르면
241
+ // 도구 이름만 보이고 입력과 결과가 빈다
242
+ case 'function_call':
243
+ return [this.call(callId, payload['name'], parseArguments(payload['arguments']), at)];
244
+ case 'custom_tool_call':
245
+ return [this.call(callId, payload['name'], payload['input'] ?? '', at)];
246
+ case 'local_shell_call': {
247
+ const action = isRecord(payload['action']) ? payload['action'] : {};
248
+ return [this.call(callId, 'local_shell', { command: action['command'] }, at)];
249
+ }
250
+ case 'function_call_output':
251
+ case 'custom_tool_call_output': {
252
+ const output = payload['output'];
253
+ const failed = isRecord(output) && output['success'] === false;
254
+ return [toolResultEvent(callId, () => outputText(output), failed, at, this.options)];
255
+ }
256
+ default:
257
+ if (typeof kind !== 'string' || !KNOWN_DROPPED_ITEMS.has(kind))
258
+ this.unknown++;
259
+ return [];
260
+ }
261
+ }
262
+ call(id, rawName, input, at) {
263
+ const name = typeof rawName === 'string' ? this.redact(rawName) : '(이름 없음)';
264
+ return toolCallEvent(id, name, input, at, this.options);
265
+ }
266
+ redact(text) {
267
+ return redactText(text, this.options);
268
+ }
269
+ }
270
+ /** function_call의 arguments는 JSON 글자다. 객체로 읽히면 키 이름 가리기도 타게 객체로 넘긴다 */
271
+ function parseArguments(raw) {
272
+ if (typeof raw !== 'string')
273
+ return raw ?? {};
274
+ try {
275
+ return JSON.parse(raw);
276
+ }
277
+ catch {
278
+ return raw;
279
+ }
280
+ }
281
+ /**
282
+ * 도구 결과 글자. 글자이거나 `{content}` 객체이거나 `{type: 'input_text', text}` 블록 배열이다.
283
+ * 이미지 블록은 표시만 남긴다.
284
+ */
285
+ function outputText(output) {
286
+ if (typeof output === 'string')
287
+ return output;
288
+ if (isRecord(output))
289
+ return outputText(output['content']);
290
+ if (!Array.isArray(output))
291
+ return '';
292
+ const parts = [];
293
+ for (const block of output) {
294
+ if (!isRecord(block))
295
+ continue;
296
+ if (typeof block['text'] === 'string')
297
+ parts.push(block['text']);
298
+ else if (block['type'] === 'input_image')
299
+ parts.push('[이미지]');
300
+ }
301
+ return parts.join('');
302
+ }
303
+ //# sourceMappingURL=codex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../../src/peer/codex.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { PeerRequest, PeerResponse } from './protocol.js';
1
+ import type { PeekNotice, PeerRequest, PeerResponse, PendingWatcher } from './protocol.js';
2
2
  import type { PeerNetworkOptions } from './network.js';
3
3
  export interface PeerDaemonOptions {
4
4
  root: string;
@@ -10,6 +10,16 @@ export interface PeerDaemonOptions {
10
10
  home?: string;
11
11
  /** 릴레이에 다시 붙는 간격 같은 것. 테스트가 줄인다 */
12
12
  network?: PeerNetworkOptions['transport'];
13
+ /** 첫 접속 승인을 기다리는 시한. 테스트가 줄인다 */
14
+ approvalTtlMs?: number;
15
+ /** 승인 대기를 알리는 시간. 이 동안은 긴 안내 문구를 붙이고 지나면 짧은 한 줄로 바꾼다. 테스트가 줄인다 */
16
+ approvalNoticeMs?: number;
17
+ /** 요약을 가져갔다고 주인 세션에 알리는 시간. 테스트가 줄인다 */
18
+ peekNoticeMs?: number;
19
+ /** 보는 쪽이 요약 답을 기다리는 시한. 테스트가 줄인다 */
20
+ peekTimeoutMs?: number;
21
+ /** 발췌를 넣을 내 세션을 찾는 Claude Code 설정 디렉토리. 기본은 데몬 환경의 claudeConfigDir() */
22
+ configDir?: string;
13
23
  }
14
24
  /**
15
25
  * `gestalt peer daemon`. 공유를 들고 대화 기록을 따라 읽어 로컬 뷰어로 흘린다. 팀에
@@ -36,6 +46,17 @@ export declare class PeerDaemon {
36
46
  /** listen할 임시 이름. 권한을 좁힌 뒤 진짜 이름으로 링크한다 */
37
47
  private readonly tmpSock;
38
48
  private readonly pollMs;
49
+ /** 훅 상태 파일을 다시 쓰기로 예약했는지. 한 틱 안의 바뀜을 한 번에 쓴다 */
50
+ private watchingQueued;
51
+ /** 세션마다 마지막으로 쓴 훅 출력. 같으면 다시 안 쓴다 */
52
+ private watchingWritten;
53
+ /**
54
+ * 이 프로세스가 시작한 시각을 ps로 읽은 글자. 훅이 같은 pid의 시작 시각과 맞춰 봐서 데몬이 죽은 뒤
55
+ * 그 pid를 받은 다른 프로세스를 데몬으로 믿지 않게 한다. ps를 못 부르면 빈 글자다
56
+ */
57
+ private readonly startStamp;
58
+ /** 보기마다 `peer watch`를 친 쪽의 Claude Code 설정 디렉토리. 발췌를 넣을 내 세션을 거기서 찾는다 */
59
+ private watchConfigDirs;
39
60
  constructor(options: PeerDaemonOptions);
40
61
  get socketPath(): string;
41
62
  get viewerPort(): number | undefined;
@@ -51,13 +72,55 @@ export declare class PeerDaemon {
51
72
  */
52
73
  private closeShareSafely;
53
74
  handle(req: PeerRequest): PeerResponse | Promise<PeerResponse>;
75
+ /** kick, approve, deny. share가 없으면 열린 공유 전부에 건다 */
76
+ private control;
77
+ private config;
78
+ /**
79
+ * ges_peer ask_user. 그 세션 id로 연 Claude Code 공유를 찾아 지금 보는 팀원에게 질문을 보낸다.
80
+ * 메시지를 끈 공유는 고르지 않는다. 답이 메시지와 같은 길로 들어가는데 주인이 그 길을 막았다.
81
+ * 질문 글자는 이 머신을 떠나므로 대화 기록과 같은 가리기를 건다.
82
+ */
83
+ private ask;
84
+ /**
85
+ * ges_peer peek. 보고 있는 원격 공유의 요약을 주인 데몬에 청해 틀로 감싼 글자로 돌려준다. 받아 줄지는
86
+ * 주인 데몬이 정한다. 보는 쪽은 받은 요약의 꼴과 크기를 다시 본 뒤에 감싼다.
87
+ */
88
+ private peek;
89
+ /**
90
+ * 고른 줄을 보는 사람 머신의 세션에 `<peer-excerpt>`로 넣는다. 글자는 브라우저가 보낸 것을 쓰지
91
+ * 않고 보기가 들고 있는 이벤트에서 다시 만든다. 넣는 길은 주인 데몬의 메시지와 같은 인박스 소켓
92
+ * 쓰기다. 데몬은 그 세션의 자식이 아니라서 내 세션이라도 수신 규칙(crossSessionInbound)을 탄다.
93
+ * 그 세션 대화 기록은 따라 읽지 않으므로 들어갔는지는 확인하지 않는다.
94
+ */
95
+ private sendExcerpt;
96
+ /** 발췌를 넣을 수 있는 내 세션. 인박스 소켓이 있고 프로세스가 살아 있는 것만 */
97
+ private localSessions;
98
+ /** 발췌를 넣을 세션을 찾는 설정 디렉토리. `peer watch`를 친 쪽 것이 먼저고 데몬 것이 다음이다 */
99
+ private sessionConfigDirs;
54
100
  private withNetwork;
55
101
  private withNetworkAsync;
102
+ /**
103
+ * 팀원이 보낸 메시지나 서명을 확인한 답을 주인 세션 인박스에 쓴다. 들어간 게 대화 기록에 보이면
104
+ * 대화 흐름에 끼우고 onSeen을 부른다. 지켜보는 일은 쓰기 전에 걸어야 쓰자마자 생긴 줄을 놓치지 않는다.
105
+ */
106
+ private deliverMessage;
56
107
  private viewerUrl;
57
108
  private announceShares;
58
109
  private openShare;
59
110
  private closeShare;
60
111
  private info;
112
+ private scheduleWatching;
113
+ /**
114
+ * 보는 중 표시 훅이 읽을 세션별 상태 파일을 다시 쓴다. 원격으로 보는 사람이나 승인을 기다리는
115
+ * 사람이 있거나 최근 10분(PEEK_NOTICE_MS) 안에 팀원의 에이전트가 요약을 가져간 세션만 파일이 있다. 훅은 파일이 있으면 적힌 데몬이 살아 있는 한 그 내용을 그대로
116
+ * 내보낸다. 아무도 없는 세션은 파일을 지워서 끊긴 사람이 다음 프롬프트에 계속 보이지 않게 한다.
117
+ * `--transcript`로 연 공유는 세션 id가 없어서 표시하지 않는다.
118
+ *
119
+ * 마지막에 쓴 내용을 세션마다 기억해 같은 내용이면 건너뛰고 쓰기와 지우기는 파일마다 따로 실패를
120
+ * 처리한다. 디렉토리를 못 만들면 그 차례는 아무것도 안 쓴다.
121
+ */
122
+ private writeWatching;
123
+ private clearWatching;
61
124
  private status;
62
125
  /**
63
126
  * 남은 소켓 파일을 치운다. 누가 받고 있으면 데몬이 이미 떠 있는 거라 던진다.
@@ -80,4 +143,16 @@ export declare class PeerDaemon {
80
143
  private serve;
81
144
  private answer;
82
145
  }
146
+ /**
147
+ * 훅이 주인 세션 모델에 붙일 글자. 이름은 명단에서 온 값이지만 모델 컨텍스트로 들어가므로 한 줄
148
+ * 라벨로 정리하고 이름 꼴이 아니면 뺀다. 승인 명령은 모델이 직접 치지 않게 적는다. 주인이
149
+ * 받아 주는 자리를 모델이 대신 채우면 승인이 뜻이 없다.
150
+ */
151
+ export declare function watchingContext(watchers: string[], pending: PendingWatcher[], peeks?: PeekNotice[]): string;
152
+ /**
153
+ * pid의 시작 시각을 ps로 읽어 공백을 뺀 글자로. 훅(`scripts/peer-watching-hook.sh`)이 같은 명령으로
154
+ * 읽어 맞춰 본다. 로캘과 시간대에 따라 글자가 달라지지 않게 LC_ALL=C, TZ=UTC로 부른다. 데몬과 세션이
155
+ * 다른 TZ로 떠도 같은 프로세스면 같은 글자가 나와야 한다.
156
+ */
157
+ export declare function processStartStamp(pid: number): string;
83
158
  //# sourceMappingURL=daemon.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../../src/peer/daemon.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAgB,WAAW,EAAE,YAAY,EAAa,MAAM,eAAe,CAAC;AAQxF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGvD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,OAAO,CAAC,EAAE,kBAAkB,CAAC,WAAW,CAAC,CAAC;CAC3C;AAsBD;;;;;;GAMG;AACH,qBAAa,UAAU;IAkBT,OAAO,CAAC,QAAQ,CAAC,OAAO;IAjBpC,OAAO,CAAC,GAAG,CAAuB;IAClC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,GAAG,CAA2B;IACtC,OAAO,CAAC,IAAI,CAA2B;IACvC,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,KAAK,CAAqB;IAClC,iDAAiD;IACjD,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,2CAA2C;IAC3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEH,OAAO,EAAE,iBAAiB;IAevD,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,IAAI,UAAU,IAAI,MAAM,GAAG,SAAS,CAEnC;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA6CtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAiC3B,oCAAoC;IACpC,IAAI,CAAC,GAAG,SAAa,GAAG,IAAI;IAyB5B;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAQxB,MAAM,CAAC,GAAG,EAAE,WAAW,GAAG,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAuD9D,OAAO,CAAC,WAAW;YASL,gBAAgB;IAS9B,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,SAAS;IA8DjB,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,IAAI;IAuBZ,OAAO,CAAC,MAAM;IAed;;;;;;;OAOG;YACW,gBAAgB;IAkB9B;;;;;;OAMG;IACH,OAAO,CAAC,SAAS;IA+BjB,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,KAAK;YAoCC,MAAM;CAoBrB"}
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../../src/peer/daemon.ts"],"names":[],"mappings":"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"}