clanka 0.0.1
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 +3 -0
- package/dist/Agent.d.ts +119 -0
- package/dist/Agent.d.ts.map +1 -0
- package/dist/Agent.js +240 -0
- package/dist/Agent.js.map +1 -0
- package/dist/AgentTools.d.ts +246 -0
- package/dist/AgentTools.d.ts.map +1 -0
- package/dist/AgentTools.js +374 -0
- package/dist/AgentTools.js.map +1 -0
- package/dist/AgentTools.test.d.ts +2 -0
- package/dist/AgentTools.test.d.ts.map +1 -0
- package/dist/AgentTools.test.js +147 -0
- package/dist/AgentTools.test.js.map +1 -0
- package/dist/ApplyPatch.d.ts +27 -0
- package/dist/ApplyPatch.d.ts.map +1 -0
- package/dist/ApplyPatch.js +343 -0
- package/dist/ApplyPatch.js.map +1 -0
- package/dist/ApplyPatch.test.d.ts +2 -0
- package/dist/ApplyPatch.test.d.ts.map +1 -0
- package/dist/ApplyPatch.test.js +99 -0
- package/dist/ApplyPatch.test.js.map +1 -0
- package/dist/Codex.d.ts +11 -0
- package/dist/Codex.d.ts.map +1 -0
- package/dist/Codex.js +14 -0
- package/dist/Codex.js.map +1 -0
- package/dist/CodexAuth.d.ts +68 -0
- package/dist/CodexAuth.d.ts.map +1 -0
- package/dist/CodexAuth.js +270 -0
- package/dist/CodexAuth.js.map +1 -0
- package/dist/CodexAuth.test.d.ts +2 -0
- package/dist/CodexAuth.test.d.ts.map +1 -0
- package/dist/CodexAuth.test.js +425 -0
- package/dist/CodexAuth.test.js.map +1 -0
- package/dist/Executor.d.ts +20 -0
- package/dist/Executor.d.ts.map +1 -0
- package/dist/Executor.js +76 -0
- package/dist/Executor.js.map +1 -0
- package/dist/OutputFormatter.d.ts +11 -0
- package/dist/OutputFormatter.d.ts.map +1 -0
- package/dist/OutputFormatter.js +5 -0
- package/dist/OutputFormatter.js.map +1 -0
- package/dist/ToolkitRenderer.d.ts +17 -0
- package/dist/ToolkitRenderer.d.ts.map +1 -0
- package/dist/ToolkitRenderer.js +25 -0
- package/dist/ToolkitRenderer.js.map +1 -0
- package/dist/TypeBuilder.d.ts +11 -0
- package/dist/TypeBuilder.d.ts.map +1 -0
- package/dist/TypeBuilder.js +383 -0
- package/dist/TypeBuilder.js.map +1 -0
- package/dist/TypeBuilder.test.d.ts +2 -0
- package/dist/TypeBuilder.test.d.ts.map +1 -0
- package/dist/TypeBuilder.test.js +243 -0
- package/dist/TypeBuilder.test.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/package.json +72 -0
- package/src/Agent.ts +398 -0
- package/src/AgentTools.test.ts +215 -0
- package/src/AgentTools.ts +507 -0
- package/src/ApplyPatch.test.ts +154 -0
- package/src/ApplyPatch.ts +473 -0
- package/src/Codex.ts +14 -0
- package/src/CodexAuth.test.ts +729 -0
- package/src/CodexAuth.ts +571 -0
- package/src/Executor.ts +129 -0
- package/src/OutputFormatter.ts +17 -0
- package/src/ToolkitRenderer.ts +39 -0
- package/src/TypeBuilder.test.ts +508 -0
- package/src/TypeBuilder.ts +670 -0
- package/src/index.ts +29 -0
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type Chunk = {
|
|
6
|
+
readonly old: ReadonlyArray<string>
|
|
7
|
+
readonly next: ReadonlyArray<string>
|
|
8
|
+
readonly ctx?: string
|
|
9
|
+
readonly eof?: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
type Wrapped = {
|
|
13
|
+
readonly path: string
|
|
14
|
+
readonly chunks: ReadonlyArray<Chunk>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type FilePatch =
|
|
18
|
+
| {
|
|
19
|
+
readonly type: "add"
|
|
20
|
+
readonly path: string
|
|
21
|
+
readonly content: string
|
|
22
|
+
}
|
|
23
|
+
| {
|
|
24
|
+
readonly type: "delete"
|
|
25
|
+
readonly path: string
|
|
26
|
+
}
|
|
27
|
+
| {
|
|
28
|
+
readonly type: "update"
|
|
29
|
+
readonly path: string
|
|
30
|
+
readonly chunks: ReadonlyArray<Chunk>
|
|
31
|
+
readonly movePath?: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const BEGIN = "*** Begin Patch"
|
|
35
|
+
const END = "*** End Patch"
|
|
36
|
+
const ADD = "*** Add File:"
|
|
37
|
+
const DELETE = "*** Delete File:"
|
|
38
|
+
const MOVE = "*** Move to:"
|
|
39
|
+
const UPDATE = "*** Update File:"
|
|
40
|
+
|
|
41
|
+
const stripHeredoc = (input: string): string => {
|
|
42
|
+
const match = input.match(
|
|
43
|
+
/^(?:cat\s+)?<<['"]?(\w+)['"]?\s*\n([\s\S]*?)\n\1\s*$/,
|
|
44
|
+
)
|
|
45
|
+
return match?.[2] ?? input
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const normalize = (input: string): string =>
|
|
49
|
+
stripHeredoc(input.replace(/\r\n/g, "\n").replace(/\r/g, "\n").trim())
|
|
50
|
+
|
|
51
|
+
const fail = (message: string): never => {
|
|
52
|
+
throw new Error(`applyPatch verification failed: ${message}`)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const locate = (text: string) => {
|
|
56
|
+
const lines = text.split("\n")
|
|
57
|
+
const begin = lines.findIndex((line) => line === BEGIN)
|
|
58
|
+
const end = lines.findIndex((line) => line === END)
|
|
59
|
+
if (begin === -1 || end === -1 || begin >= end) {
|
|
60
|
+
fail("Invalid patch format: missing Begin/End markers")
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
lines,
|
|
64
|
+
begin,
|
|
65
|
+
end,
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const parseChunks = (
|
|
70
|
+
lines: ReadonlyArray<string>,
|
|
71
|
+
start: number,
|
|
72
|
+
end = lines.length,
|
|
73
|
+
) => {
|
|
74
|
+
const chunks = Array<Chunk>()
|
|
75
|
+
let i = start
|
|
76
|
+
|
|
77
|
+
while (i < end) {
|
|
78
|
+
const line = lines[i]!
|
|
79
|
+
if (line.startsWith("***")) {
|
|
80
|
+
break
|
|
81
|
+
}
|
|
82
|
+
if (!line.startsWith("@@")) {
|
|
83
|
+
i++
|
|
84
|
+
continue
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const ctx = line.slice(2).trim()
|
|
88
|
+
const old = Array<string>()
|
|
89
|
+
const next = Array<string>()
|
|
90
|
+
let eof = false
|
|
91
|
+
i++
|
|
92
|
+
|
|
93
|
+
while (i < end) {
|
|
94
|
+
const line = lines[i]!
|
|
95
|
+
if (line === "*** End of File") {
|
|
96
|
+
eof = true
|
|
97
|
+
i++
|
|
98
|
+
break
|
|
99
|
+
}
|
|
100
|
+
if (line.startsWith("@@") || line.startsWith("***")) {
|
|
101
|
+
break
|
|
102
|
+
}
|
|
103
|
+
if (line.startsWith(" ")) {
|
|
104
|
+
const text = line.slice(1)
|
|
105
|
+
old.push(text)
|
|
106
|
+
next.push(text)
|
|
107
|
+
} else if (line.startsWith("-")) {
|
|
108
|
+
old.push(line.slice(1))
|
|
109
|
+
} else if (line.startsWith("+")) {
|
|
110
|
+
next.push(line.slice(1))
|
|
111
|
+
}
|
|
112
|
+
i++
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
chunks.push({
|
|
116
|
+
old,
|
|
117
|
+
next,
|
|
118
|
+
...(ctx.length > 0 ? { ctx } : {}),
|
|
119
|
+
...(eof ? { eof: true } : {}),
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
chunks,
|
|
125
|
+
next: i,
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const parseWrapped = (text: string): Wrapped => {
|
|
130
|
+
const { lines, begin, end } = locate(text)
|
|
131
|
+
|
|
132
|
+
let i = begin + 1
|
|
133
|
+
while (i < end && lines[i]!.trim() === "") {
|
|
134
|
+
i++
|
|
135
|
+
}
|
|
136
|
+
if (i === end) {
|
|
137
|
+
throw new Error("patch rejected: empty patch")
|
|
138
|
+
}
|
|
139
|
+
if (!lines[i]!.startsWith(UPDATE)) {
|
|
140
|
+
fail("only single-file update patches are supported")
|
|
141
|
+
}
|
|
142
|
+
const path = lines[i]!.slice(UPDATE.length).trim()
|
|
143
|
+
if (path.length === 0) {
|
|
144
|
+
fail("missing update file path")
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
i++
|
|
148
|
+
if (i < end && lines[i]!.startsWith(MOVE)) {
|
|
149
|
+
fail("move patches are not supported")
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const parsed = parseChunks(lines, i, end)
|
|
153
|
+
if (parsed.chunks.length === 0) {
|
|
154
|
+
fail("no hunks found")
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
i = parsed.next
|
|
158
|
+
while (i < end && lines[i]!.trim() === "") {
|
|
159
|
+
i++
|
|
160
|
+
}
|
|
161
|
+
if (i !== end) {
|
|
162
|
+
fail("only one update file section is supported")
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
path,
|
|
167
|
+
chunks: parsed.chunks,
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const parseAdd = (lines: ReadonlyArray<string>, start: number, end: number) => {
|
|
172
|
+
const out = Array<string>()
|
|
173
|
+
let i = start
|
|
174
|
+
|
|
175
|
+
while (i < end) {
|
|
176
|
+
const line = lines[i]!
|
|
177
|
+
if (line.startsWith("***")) {
|
|
178
|
+
break
|
|
179
|
+
}
|
|
180
|
+
if (line.startsWith("+")) {
|
|
181
|
+
out.push(line.slice(1))
|
|
182
|
+
}
|
|
183
|
+
i++
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
content: out.join("\n"),
|
|
188
|
+
next: i,
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export const parsePatch = (input: string): ReadonlyArray<FilePatch> => {
|
|
193
|
+
const text = normalize(input)
|
|
194
|
+
if (text.length === 0) {
|
|
195
|
+
throw new Error("patchText is required")
|
|
196
|
+
}
|
|
197
|
+
if (text === `${BEGIN}\n${END}`) {
|
|
198
|
+
throw new Error("patch rejected: empty patch")
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const { lines, begin, end } = locate(text)
|
|
202
|
+
const out = Array<FilePatch>()
|
|
203
|
+
let i = begin + 1
|
|
204
|
+
|
|
205
|
+
while (i < end) {
|
|
206
|
+
while (i < end && lines[i]!.trim() === "") {
|
|
207
|
+
i++
|
|
208
|
+
}
|
|
209
|
+
if (i === end) {
|
|
210
|
+
break
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const line = lines[i]!
|
|
214
|
+
if (line.startsWith(ADD)) {
|
|
215
|
+
const path = line.slice(ADD.length).trim()
|
|
216
|
+
if (path.length === 0) {
|
|
217
|
+
fail("missing add file path")
|
|
218
|
+
}
|
|
219
|
+
const parsed = parseAdd(lines, i + 1, end)
|
|
220
|
+
out.push({
|
|
221
|
+
type: "add",
|
|
222
|
+
path,
|
|
223
|
+
content: parsed.content,
|
|
224
|
+
})
|
|
225
|
+
i = parsed.next
|
|
226
|
+
continue
|
|
227
|
+
}
|
|
228
|
+
if (line.startsWith(DELETE)) {
|
|
229
|
+
const path = line.slice(DELETE.length).trim()
|
|
230
|
+
if (path.length === 0) {
|
|
231
|
+
fail("missing delete file path")
|
|
232
|
+
}
|
|
233
|
+
out.push({
|
|
234
|
+
type: "delete",
|
|
235
|
+
path,
|
|
236
|
+
})
|
|
237
|
+
i++
|
|
238
|
+
continue
|
|
239
|
+
}
|
|
240
|
+
if (line.startsWith(UPDATE)) {
|
|
241
|
+
const path = line.slice(UPDATE.length).trim()
|
|
242
|
+
if (path.length === 0) {
|
|
243
|
+
fail("missing update file path")
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
i++
|
|
247
|
+
let movePath: string | undefined
|
|
248
|
+
if (i < end && lines[i]!.startsWith(MOVE)) {
|
|
249
|
+
movePath = lines[i]!.slice(MOVE.length).trim()
|
|
250
|
+
if (movePath.length === 0) {
|
|
251
|
+
fail("missing move file path")
|
|
252
|
+
}
|
|
253
|
+
i++
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const parsed = parseChunks(lines, i, end)
|
|
257
|
+
if (parsed.chunks.length === 0) {
|
|
258
|
+
fail("no hunks found")
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
out.push({
|
|
262
|
+
type: "update",
|
|
263
|
+
path,
|
|
264
|
+
chunks: parsed.chunks,
|
|
265
|
+
...(movePath === undefined ? {} : { movePath }),
|
|
266
|
+
})
|
|
267
|
+
i = parsed.next
|
|
268
|
+
continue
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
fail(`unexpected line in wrapped patch: ${line}`)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (out.length === 0) {
|
|
275
|
+
fail("no hunks found")
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return out
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export const wrappedPath = (input: string): string | undefined => {
|
|
282
|
+
const text = normalize(input)
|
|
283
|
+
if (!text.startsWith(BEGIN)) {
|
|
284
|
+
return
|
|
285
|
+
}
|
|
286
|
+
return parseWrapped(text).path
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const parse = (input: string): ReadonlyArray<Chunk> => {
|
|
290
|
+
const text = normalize(input)
|
|
291
|
+
if (text.length === 0) {
|
|
292
|
+
throw new Error("patchText is required")
|
|
293
|
+
}
|
|
294
|
+
if (text === `${BEGIN}\n${END}`) {
|
|
295
|
+
throw new Error("patch rejected: empty patch")
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (text.startsWith(BEGIN)) {
|
|
299
|
+
return parseWrapped(text).chunks
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const parsed = parseChunks(text.split("\n"), 0)
|
|
303
|
+
if (parsed.chunks.length === 0) {
|
|
304
|
+
fail("no hunks found")
|
|
305
|
+
}
|
|
306
|
+
return parsed.chunks
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const normalizeUnicode = (line: string): string =>
|
|
310
|
+
line
|
|
311
|
+
.replace(/[\u2018\u2019\u201A\u201B]/g, "'")
|
|
312
|
+
.replace(/[\u201C\u201D\u201E\u201F]/g, '"')
|
|
313
|
+
.replace(/[\u2010\u2011\u2012\u2013\u2014\u2015]/g, "-")
|
|
314
|
+
.replace(/\u2026/g, "...")
|
|
315
|
+
.replace(/\u00A0/g, " ")
|
|
316
|
+
|
|
317
|
+
const match = (
|
|
318
|
+
lines: ReadonlyArray<string>,
|
|
319
|
+
part: ReadonlyArray<string>,
|
|
320
|
+
from: number,
|
|
321
|
+
same: (left: string, right: string) => boolean,
|
|
322
|
+
eof: boolean,
|
|
323
|
+
): number => {
|
|
324
|
+
if (eof) {
|
|
325
|
+
const last = lines.length - part.length
|
|
326
|
+
if (last >= from) {
|
|
327
|
+
let ok = true
|
|
328
|
+
for (let i = 0; i < part.length; i++) {
|
|
329
|
+
if (!same(lines[last + i]!, part[i]!)) {
|
|
330
|
+
ok = false
|
|
331
|
+
break
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
if (ok) {
|
|
335
|
+
return last
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
for (let i = from; i <= lines.length - part.length; i++) {
|
|
341
|
+
let ok = true
|
|
342
|
+
for (let j = 0; j < part.length; j++) {
|
|
343
|
+
if (!same(lines[i + j]!, part[j]!)) {
|
|
344
|
+
ok = false
|
|
345
|
+
break
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (ok) {
|
|
349
|
+
return i
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return -1
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const seek = (
|
|
357
|
+
lines: ReadonlyArray<string>,
|
|
358
|
+
part: ReadonlyArray<string>,
|
|
359
|
+
from: number,
|
|
360
|
+
eof = false,
|
|
361
|
+
): number => {
|
|
362
|
+
if (part.length === 0) {
|
|
363
|
+
return -1
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const exact = match(lines, part, from, (left, right) => left === right, eof)
|
|
367
|
+
if (exact !== -1) {
|
|
368
|
+
return exact
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const rstrip = match(
|
|
372
|
+
lines,
|
|
373
|
+
part,
|
|
374
|
+
from,
|
|
375
|
+
(left, right) => left.trimEnd() === right.trimEnd(),
|
|
376
|
+
eof,
|
|
377
|
+
)
|
|
378
|
+
if (rstrip !== -1) {
|
|
379
|
+
return rstrip
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
const trim = match(
|
|
383
|
+
lines,
|
|
384
|
+
part,
|
|
385
|
+
from,
|
|
386
|
+
(left, right) => left.trim() === right.trim(),
|
|
387
|
+
eof,
|
|
388
|
+
)
|
|
389
|
+
if (trim !== -1) {
|
|
390
|
+
return trim
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
return match(
|
|
394
|
+
lines,
|
|
395
|
+
part,
|
|
396
|
+
from,
|
|
397
|
+
(left, right) =>
|
|
398
|
+
normalizeUnicode(left.trim()) === normalizeUnicode(right.trim()),
|
|
399
|
+
eof,
|
|
400
|
+
)
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
const compute = (
|
|
404
|
+
file: string,
|
|
405
|
+
lines: ReadonlyArray<string>,
|
|
406
|
+
chunks: ReadonlyArray<Chunk>,
|
|
407
|
+
): Array<readonly [number, number, ReadonlyArray<string>]> => {
|
|
408
|
+
const out = Array<readonly [number, number, ReadonlyArray<string>]>()
|
|
409
|
+
let from = 0
|
|
410
|
+
|
|
411
|
+
for (const chunk of chunks) {
|
|
412
|
+
if (chunk.ctx) {
|
|
413
|
+
const at = seek(lines, [chunk.ctx], from)
|
|
414
|
+
if (at === -1) {
|
|
415
|
+
fail(`Failed to find context '${chunk.ctx}' in ${file}`)
|
|
416
|
+
}
|
|
417
|
+
from = at + 1
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
if (chunk.old.length === 0) {
|
|
421
|
+
out.push([lines.length, 0, chunk.next])
|
|
422
|
+
continue
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
let old = chunk.old
|
|
426
|
+
let next = chunk.next
|
|
427
|
+
let at = seek(lines, old, from, chunk.eof === true)
|
|
428
|
+
if (at === -1 && old.at(-1) === "") {
|
|
429
|
+
old = old.slice(0, -1)
|
|
430
|
+
next = next.at(-1) === "" ? next.slice(0, -1) : next
|
|
431
|
+
at = seek(lines, old, from, chunk.eof === true)
|
|
432
|
+
}
|
|
433
|
+
if (at === -1) {
|
|
434
|
+
fail(`Failed to find expected lines in ${file}:\n${chunk.old.join("\n")}`)
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
out.push([at, old.length, next])
|
|
438
|
+
from = at + old.length
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
out.sort((left, right) => left[0] - right[0])
|
|
442
|
+
return out
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
export const patchChunks = (
|
|
446
|
+
file: string,
|
|
447
|
+
input: string,
|
|
448
|
+
chunks: ReadonlyArray<Chunk>,
|
|
449
|
+
): string => {
|
|
450
|
+
const eol = input.includes("\r\n") ? "\r\n" : "\n"
|
|
451
|
+
const lines = input.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n")
|
|
452
|
+
if (lines.at(-1) === "") {
|
|
453
|
+
lines.pop()
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
const out = [...lines]
|
|
457
|
+
for (const [at, size, next] of compute(file, lines, chunks).reverse()) {
|
|
458
|
+
out.splice(at, size, ...next)
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (out.at(-1) !== "") {
|
|
462
|
+
out.push("")
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
const text = out.join("\n")
|
|
466
|
+
return eol === "\r\n" ? text.replace(/\n/g, "\r\n") : text
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
export const patchContent = (
|
|
470
|
+
file: string,
|
|
471
|
+
input: string,
|
|
472
|
+
patchText: string,
|
|
473
|
+
): string => patchChunks(file, input, parse(patchText))
|
package/src/Codex.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import { OpenAiClient } from "@effect/ai-openai"
|
|
5
|
+
import { Layer } from "effect"
|
|
6
|
+
import { CodexAuth } from "./CodexAuth.ts"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @since 1.0.0
|
|
10
|
+
* @category Layers
|
|
11
|
+
*/
|
|
12
|
+
export const CodexAiClient = OpenAiClient.layer({
|
|
13
|
+
apiUrl: "https://chatgpt.com/backend-api/codex",
|
|
14
|
+
}).pipe(Layer.provide(CodexAuth.layerClient))
|