agent-work-loop 0.6.26 → 0.6.30
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 +28 -0
- package/dist/{brief-JIXESFMO.js → brief-O6IGLOPY.js} +5 -5
- package/dist/{changelog-PBF6JBOC.js → changelog-4XKSWJX2.js} +5 -5
- package/dist/{chunk-PUI2B27T.js → chunk-3CR74VLL.js} +111 -14
- package/dist/{chunk-YODF2HTK.js → chunk-45X7T64Y.js} +12 -37
- package/dist/{chunk-F34MITMC.js → chunk-7WDDWO2B.js} +3 -3
- package/dist/{chunk-XD4IDIEM.js → chunk-7WE2E76P.js} +6 -6
- package/dist/{chunk-2YWYGWCZ.js → chunk-AYFHV27J.js} +70 -32
- package/dist/{chunk-JDCW2Y2G.js → chunk-FJKJTXN4.js} +7 -7
- package/dist/{chunk-NXH5EBBJ.js → chunk-FOTWJOWF.js} +8 -8
- package/dist/{chunk-OPPRCJT2.js → chunk-FUP7DKT3.js} +7 -7
- package/dist/{chunk-AMQFBJCO.js → chunk-IEFYCUWX.js} +18 -8
- package/dist/{chunk-SQFGUNTY.js → chunk-ILXQGAUE.js} +5 -5
- package/dist/{chunk-KEVDO3C3.js → chunk-R4LFOY5M.js} +9 -9
- package/dist/{chunk-B6AEYNF3.js → chunk-RAMHRXFX.js} +40 -23
- package/dist/{chunk-PLHEP5QE.js → chunk-RXG6BUQ6.js} +5 -5
- package/dist/{chunk-6DXZYTDA.js → chunk-TTLFDLK6.js} +6 -6
- package/dist/{chunk-XQ7JJXBY.js → chunk-VX23A4FW.js} +7 -7
- package/dist/{chunk-FQLRA2YC.js → chunk-WZCIAGNJ.js} +1 -1
- package/dist/cli.js +61 -53
- package/dist/{commit-OUZNLCNL.js → commit-2UFIIERX.js} +6 -6
- package/dist/{config-26FHYODU.js → config-D7LUIZYA.js} +3 -3
- package/dist/{doctor-UHUA6ULF.js → doctor-IAK57PIS.js} +8 -8
- package/dist/{evolve-V5BQCSHC.js → evolve-RMKOBGSK.js} +7 -7
- package/dist/{feedback-UJ7WSARN.js → feedback-RT63F57C.js} +8 -8
- package/dist/{gotchas-L3NXDDDI.js → gotchas-DM7BXF77.js} +11 -11
- package/dist/{hold-recheck-QINLKCPM.js → hold-recheck-I6JMGTP6.js} +18 -18
- package/dist/{init-6R4MT6FQ.js → init-XUJTEY2Y.js} +6 -2
- package/dist/lane-OZ5WGGDT.js +41 -0
- package/dist/{loop-summary-FVJICIWA.js → loop-summary-7HMFHKUD.js} +10 -10
- package/dist/{metrics-NVJFKQ4J.js → metrics-F3YDMURU.js} +4 -4
- package/dist/{record-JJJSGU5E.js → record-ZNGMMZHF.js} +5 -5
- package/dist/{review-I4QMZPTI.js → review-R5I4KYFN.js} +16 -16
- package/dist/{rules-OTUONMXO.js → rules-GVDXKROQ.js} +8 -8
- package/dist/{state-UC45ECTI.js → state-B45D6VSF.js} +4 -4
- package/dist/status-7SBNSHTV.js +40 -0
- package/dist/{uninstall-HHKLOXF5.js → uninstall-Q6KJYH5E.js} +17 -17
- package/dist/update-WHHGVXIY.js +135 -0
- package/dist/{verify-A64P77RU.js → verify-ZBDWID5U.js} +10 -10
- package/dist/version-check-3NVRLYUF.js +14 -0
- package/dist/{work-LMM5W2PQ.js → work-EVYCDIPE.js} +14 -14
- package/engine/version.json +1 -1
- package/package.json +1 -1
- package/dist/lane-CJVXEV3A.js +0 -41
- package/dist/status-TU36KJDH.js +0 -40
- package/dist/update-BXRWE7OH.js +0 -61
- package/dist/version-check-UBXBVPTS.js +0 -14
package/README.md
CHANGED
|
@@ -43,6 +43,34 @@ yarn global add agent-work-loop
|
|
|
43
43
|
> ```
|
|
44
44
|
> `dist/cli.js`가 `awl` bin으로 등록됩니다. 정식 npm 배포가 되면 이 문단은 지웁니다.
|
|
45
45
|
|
|
46
|
+
### 업데이트 하기
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
업데이트 하기:
|
|
50
|
+
1. npm i -g agent-work-loop@latest npm에 배포된 최신 버전을 받습니다
|
|
51
|
+
2. awl update 설치된 패키지로 전역 엔진(~/.awl/engine)을 갱신합니다
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
pnpm이나 yarn을 쓴다면 1번만 그 도구로 바꿉니다:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pnpm add -g agent-work-loop@latest
|
|
58
|
+
yarn global add agent-work-loop@latest
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`awl update`(옵션 없음)는 `awl update --global`과 같습니다. 전역 엔진만 갱신하고 어떤 프로젝트도 건드리지 않습니다. 대부분은 이 두 줄이면 끝입니다.
|
|
62
|
+
|
|
63
|
+
**여러 프로젝트를 관리하는 입장이라면** 등록된 프로젝트들의 로컬 스킬(`.claude/skills`, `AGENTS.md`, `.awl/config.json`)까지 한 번에 맞추고 싶을 수 있습니다:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npm i -g agent-work-loop@latest
|
|
67
|
+
awl update --all
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`--all`은 전역 엔진과 `~/.awl/projects.json`에 등록된 프로젝트 전부의 로컬 스킬을 갱신하고, 끝에 바뀐 프로젝트 목록과 "커밋하세요" 안내를 보여줍니다. 등록된 프로젝트만 로컬을 건드리고 싶으면 `--local`만 씁니다.
|
|
71
|
+
|
|
72
|
+
이렇게 갱신한 프로젝트를 커밋해서 push하면, 그 저장소를 쓰는 다른 사람들은 다음에 pull할 때 최신 스킬을 받습니다. **다만 자동으로 알림이 가는 구조는 아닙니다.** 각자 컴퓨터의 `~/.awl/engine`이 낡았는지는 그 사람이 `awl doctor`/`awl version-check`를 실행하거나 `/awl-loop`·`/awl-pipeline`을 실행할 때(버전 확인이 맨 처음 단계로 들어있습니다) 노란 경고로 보게 됩니다.
|
|
73
|
+
|
|
46
74
|
설치가 됐는지 확인합니다:
|
|
47
75
|
|
|
48
76
|
```bash
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadProjectName,
|
|
3
3
|
readRecords
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-TTLFDLK6.js";
|
|
5
5
|
import {
|
|
6
6
|
loadState
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-7WE2E76P.js";
|
|
8
8
|
import {
|
|
9
9
|
resolveProjectRoot,
|
|
10
10
|
run
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-RAMHRXFX.js";
|
|
12
|
+
import "./chunk-AYFHV27J.js";
|
|
13
|
+
import "./chunk-45X7T64Y.js";
|
|
14
14
|
|
|
15
15
|
// src/commands/brief.ts
|
|
16
16
|
var KST_OFFSET_MS = 9 * 60 * 60 * 1e3;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
readRecords
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-TTLFDLK6.js";
|
|
4
4
|
import {
|
|
5
5
|
loadState
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-7WE2E76P.js";
|
|
7
7
|
import {
|
|
8
8
|
resolveProjectRoot
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-RAMHRXFX.js";
|
|
10
|
+
import "./chunk-AYFHV27J.js";
|
|
11
11
|
import {
|
|
12
12
|
caps,
|
|
13
13
|
signal
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-45X7T64Y.js";
|
|
15
15
|
|
|
16
16
|
// src/commands/changelog.ts
|
|
17
17
|
function runChangelogDraft(opts) {
|
|
@@ -7,39 +7,42 @@ import {
|
|
|
7
7
|
isCheckPassed,
|
|
8
8
|
runVerifyChecks,
|
|
9
9
|
writeVerifyBaseline
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-VX23A4FW.js";
|
|
11
11
|
import {
|
|
12
12
|
gitBranch
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-FOTWJOWF.js";
|
|
14
14
|
import {
|
|
15
15
|
parseRuleFile
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-RXG6BUQ6.js";
|
|
17
17
|
import {
|
|
18
18
|
nextGotchaId
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-ILXQGAUE.js";
|
|
20
|
+
import {
|
|
21
|
+
loadProjectName
|
|
22
|
+
} from "./chunk-TTLFDLK6.js";
|
|
20
23
|
import {
|
|
21
24
|
loadState,
|
|
22
25
|
migrateState,
|
|
23
26
|
writeState
|
|
24
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-7WE2E76P.js";
|
|
25
28
|
import {
|
|
26
29
|
loadConfig,
|
|
27
30
|
resolveProjectRoot,
|
|
28
31
|
run
|
|
29
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-RAMHRXFX.js";
|
|
30
33
|
import {
|
|
31
34
|
installClaudeSkill
|
|
32
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-AYFHV27J.js";
|
|
33
36
|
import {
|
|
34
37
|
caps,
|
|
35
|
-
card,
|
|
36
38
|
feedback,
|
|
37
39
|
globalRoot,
|
|
38
40
|
makeColors,
|
|
39
41
|
makeSymbols,
|
|
40
42
|
makeTokens,
|
|
43
|
+
sectionBox,
|
|
41
44
|
signal
|
|
42
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-45X7T64Y.js";
|
|
43
46
|
|
|
44
47
|
// src/commands/work.ts
|
|
45
48
|
import fs2 from "fs";
|
|
@@ -213,6 +216,88 @@ function mergeIsolatedLearning(fromRoot, toRoot) {
|
|
|
213
216
|
const generationsAdded = copyGenerations(fromRoot, toRoot);
|
|
214
217
|
return { gotchasAdded: added.length, rulesAdded, generationsAdded };
|
|
215
218
|
}
|
|
219
|
+
function recordFiles(root) {
|
|
220
|
+
const dir = path.join(root, "records");
|
|
221
|
+
try {
|
|
222
|
+
return fs.readdirSync(dir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
223
|
+
} catch {
|
|
224
|
+
return [];
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function monthOf(at) {
|
|
228
|
+
return at.slice(0, 7);
|
|
229
|
+
}
|
|
230
|
+
function copyRecordDiffs(fromRoot, toRoot) {
|
|
231
|
+
const fromDir = path.join(fromRoot, "records", "diffs");
|
|
232
|
+
if (!fs.existsSync(fromDir)) {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
const toDir = path.join(toRoot, "records", "diffs");
|
|
236
|
+
for (const f of fs.readdirSync(fromDir)) {
|
|
237
|
+
const dest = path.join(toDir, f);
|
|
238
|
+
if (!fs.existsSync(dest)) {
|
|
239
|
+
fs.mkdirSync(toDir, { recursive: true });
|
|
240
|
+
fs.copyFileSync(path.join(fromDir, f), dest);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function mergeIsolatedRecords(fromRoot, toRoot) {
|
|
245
|
+
let recordsMerged = 0;
|
|
246
|
+
for (const f of recordFiles(fromRoot)) {
|
|
247
|
+
const content = fs.readFileSync(path.join(fromRoot, "records", f), "utf8");
|
|
248
|
+
for (const line of content.split("\n")) {
|
|
249
|
+
const trimmed = line.trim();
|
|
250
|
+
if (trimmed === "") {
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
let record;
|
|
254
|
+
try {
|
|
255
|
+
record = JSON.parse(trimmed);
|
|
256
|
+
} catch {
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
const at = typeof record.at === "string" ? record.at : void 0;
|
|
260
|
+
if (!at) {
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
const dest = path.join(toRoot, "records", `${monthOf(at)}.jsonl`);
|
|
264
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
265
|
+
fs.appendFileSync(dest, `${trimmed}
|
|
266
|
+
`);
|
|
267
|
+
recordsMerged += 1;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
if (recordsMerged > 0) {
|
|
271
|
+
copyRecordDiffs(fromRoot, toRoot);
|
|
272
|
+
}
|
|
273
|
+
return { recordsMerged };
|
|
274
|
+
}
|
|
275
|
+
function archiveIsolatedRecords(fromRoot, toRoot, meta) {
|
|
276
|
+
const lines = [];
|
|
277
|
+
for (const f of recordFiles(fromRoot)) {
|
|
278
|
+
const content = fs.readFileSync(path.join(fromRoot, "records", f), "utf8");
|
|
279
|
+
for (const line of content.split("\n")) {
|
|
280
|
+
if (line.trim() !== "") {
|
|
281
|
+
lines.push(line);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (lines.length === 0) {
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
289
|
+
const dir = path.join(toRoot, "records", "archive", meta.project);
|
|
290
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
291
|
+
let dest = path.join(dir, `${date}-${meta.lane}.jsonl`);
|
|
292
|
+
let n = 2;
|
|
293
|
+
while (fs.existsSync(dest)) {
|
|
294
|
+
dest = path.join(dir, `${date}-${meta.lane}-${n}.jsonl`);
|
|
295
|
+
n += 1;
|
|
296
|
+
}
|
|
297
|
+
fs.writeFileSync(dest, `${lines.join("\n")}
|
|
298
|
+
`);
|
|
299
|
+
return dest;
|
|
300
|
+
}
|
|
216
301
|
function writeParentMarker(isolatedHome) {
|
|
217
302
|
try {
|
|
218
303
|
fs.writeFileSync(path.join(isolatedHome, PARENT_MARKER), `${globalRoot()}
|
|
@@ -230,7 +315,7 @@ function resolveParentGlobal(isolatedHome) {
|
|
|
230
315
|
}
|
|
231
316
|
return globalRoot();
|
|
232
317
|
}
|
|
233
|
-
function mergeIsolatedHome(isolatedHome) {
|
|
318
|
+
function mergeIsolatedHome(isolatedHome, meta) {
|
|
234
319
|
if (!fs.existsSync(isolatedHome)) {
|
|
235
320
|
return null;
|
|
236
321
|
}
|
|
@@ -238,7 +323,10 @@ function mergeIsolatedHome(isolatedHome) {
|
|
|
238
323
|
if (path.resolve(isolatedHome) === path.resolve(toRoot)) {
|
|
239
324
|
return null;
|
|
240
325
|
}
|
|
241
|
-
|
|
326
|
+
const learning = mergeIsolatedLearning(isolatedHome, toRoot);
|
|
327
|
+
const recordsArchivePath = archiveIsolatedRecords(isolatedHome, toRoot, meta);
|
|
328
|
+
const { recordsMerged } = mergeIsolatedRecords(isolatedHome, toRoot);
|
|
329
|
+
return { ...learning, recordsMerged, recordsArchivePath };
|
|
242
330
|
}
|
|
243
331
|
|
|
244
332
|
// src/commands/work.ts
|
|
@@ -299,7 +387,7 @@ function renderWorkList(list, c) {
|
|
|
299
387
|
const t = makeTokens(c);
|
|
300
388
|
const s = makeSymbols(c);
|
|
301
389
|
if (list.length === 0) {
|
|
302
|
-
return
|
|
390
|
+
return sectionBox(
|
|
303
391
|
"\uC6CC\uD06C\uC544\uC774\uD15C",
|
|
304
392
|
[
|
|
305
393
|
`${signal(c, "info")} \uB4F1\uB85D\uB41C \uC6CC\uD06C\uC544\uC774\uD15C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.`,
|
|
@@ -324,7 +412,7 @@ function renderWorkList(list, c) {
|
|
|
324
412
|
out.push(` ${s.lastBranch} ${color.dim(`worktree: ${w.worktreePath}`)}`);
|
|
325
413
|
}
|
|
326
414
|
}
|
|
327
|
-
return
|
|
415
|
+
return sectionBox("\uC6CC\uD06C\uC544\uC774\uD15C", out, c);
|
|
328
416
|
}
|
|
329
417
|
function registryOf(state) {
|
|
330
418
|
return state.workitems && typeof state.workitems === "object" ? state.workitems : {};
|
|
@@ -839,12 +927,17 @@ async function runWorkDone(id, opts = {}) {
|
|
|
839
927
|
const color = makeColors(c.color);
|
|
840
928
|
let worktreeNote = null;
|
|
841
929
|
let mergeNote = null;
|
|
930
|
+
let recordsNote = null;
|
|
842
931
|
const isolatedHome = result.worktree ? path2.join(result.worktree.path, ".awl", "home") : path2.join(root, ".awl", "home");
|
|
843
932
|
try {
|
|
844
|
-
const
|
|
933
|
+
const project = loadProjectName(root) ?? path2.basename(root);
|
|
934
|
+
const merged = mergeIsolatedHome(isolatedHome, { project, lane: id });
|
|
845
935
|
if (merged && (merged.gotchasAdded > 0 || merged.rulesAdded > 0 || merged.generationsAdded > 0)) {
|
|
846
936
|
mergeNote = `\uD559\uC2B5 \uC804\uC5ED \uBCD1\uD569 gotcha ${merged.gotchasAdded} \xB7 rule ${merged.rulesAdded} \xB7 generation ${merged.generationsAdded}`;
|
|
847
937
|
}
|
|
938
|
+
if (merged && merged.recordsMerged > 0) {
|
|
939
|
+
recordsNote = `records \uC804\uC5ED \uBCD1\uD569 ${merged.recordsMerged}\uAC74${merged.recordsArchivePath ? ` \xB7 \uC544\uCE74\uC774\uBE0C ${merged.recordsArchivePath}` : ""}`;
|
|
940
|
+
}
|
|
848
941
|
} catch (e) {
|
|
849
942
|
process.stderr.write(
|
|
850
943
|
`
|
|
@@ -879,6 +972,10 @@ ${feedback(c, "ok", `\uC644\uB8CC \uCC98\uB9AC ${color.bold(id)}`, "\uC0C1\uD0D
|
|
|
879
972
|
}
|
|
880
973
|
if (mergeNote) {
|
|
881
974
|
process.stdout.write(` ${color.dim(mergeNote)}
|
|
975
|
+
`);
|
|
976
|
+
}
|
|
977
|
+
if (recordsNote) {
|
|
978
|
+
process.stdout.write(` ${color.dim(recordsNote)}
|
|
882
979
|
`);
|
|
883
980
|
}
|
|
884
981
|
}
|
|
@@ -390,31 +390,6 @@ function viewportWidth() {
|
|
|
390
390
|
}
|
|
391
391
|
return HARD_MAX_WIDTH;
|
|
392
392
|
}
|
|
393
|
-
function card(title, lines, c = caps(), minInnerWidth = 0) {
|
|
394
|
-
const s = makeSymbols(c);
|
|
395
|
-
const t = makeTokens(c);
|
|
396
|
-
const pad = 2;
|
|
397
|
-
const maxInner = Math.max(
|
|
398
|
-
minInnerWidth,
|
|
399
|
-
Math.min(HARD_MAX_WIDTH, viewportWidth() - (2 + pad * 2))
|
|
400
|
-
);
|
|
401
|
-
const wrapped = lines.flatMap((line) => wrapToWidth(line, maxInner, { hanging: true }));
|
|
402
|
-
const inner = Math.min(
|
|
403
|
-
maxInner,
|
|
404
|
-
Math.max(minInnerWidth, visibleWidth(title), ...wrapped.map(visibleWidth), 0)
|
|
405
|
-
);
|
|
406
|
-
const frame = (text) => t.frame(text);
|
|
407
|
-
const row = (text) => {
|
|
408
|
-
const gap = Math.max(0, inner - visibleWidth(text));
|
|
409
|
-
return `${frame(s.boxV)}${" ".repeat(pad)}${text}${" ".repeat(gap + pad)}${frame(s.boxV)}`;
|
|
410
|
-
};
|
|
411
|
-
const safeTitle = truncateToWidth(title, inner);
|
|
412
|
-
const tvis = visibleWidth(safeTitle);
|
|
413
|
-
const dash = Math.max(1, inner + pad * 2 - 3 - tvis);
|
|
414
|
-
const top = frame(`${s.boxTL}${s.boxH} `) + t.emphasis(t.accent(safeTitle)) + frame(` ${s.boxH.repeat(dash)}${s.boxTR}`);
|
|
415
|
-
const bottom = frame(`${s.boxBL}${s.boxH.repeat(inner + pad * 2)}${s.boxBR}`);
|
|
416
|
-
return [top, ...wrapped.map(row), bottom].join("\n");
|
|
417
|
-
}
|
|
418
393
|
function sectionBox(title, lines, c = caps(), minInnerWidth = 0) {
|
|
419
394
|
const s = makeSymbols(c);
|
|
420
395
|
const t = makeTokens(c);
|
|
@@ -424,17 +399,18 @@ function sectionBox(title, lines, c = caps(), minInnerWidth = 0) {
|
|
|
424
399
|
Math.min(HARD_MAX_WIDTH, viewportWidth() - (2 + pad * 2))
|
|
425
400
|
);
|
|
426
401
|
const wrapped = lines.flatMap((line) => wrapToWidth(line, maxInner, { hanging: true }));
|
|
427
|
-
const inner = Math.min(
|
|
428
|
-
maxInner,
|
|
429
|
-
Math.max(minInnerWidth, visibleWidth(title), ...wrapped.map(visibleWidth), 0)
|
|
430
|
-
);
|
|
431
402
|
const frame = (text) => t.frame(text);
|
|
432
|
-
const
|
|
433
|
-
const
|
|
434
|
-
const
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
403
|
+
const lastLogical = lines[lines.length - 1] ?? "";
|
|
404
|
+
const lastIsBranch = lastLogical.trimStart().startsWith(s.lastBranch);
|
|
405
|
+
const row = (text, isLast) => {
|
|
406
|
+
const closeThis = isLast && !lastIsBranch;
|
|
407
|
+
const left = closeThis ? `${s.boxBL}${s.boxH}` : s.boxV;
|
|
408
|
+
const gap = closeThis ? pad - 1 : pad;
|
|
409
|
+
return `${frame(left)}${" ".repeat(gap)}${text}`;
|
|
410
|
+
};
|
|
411
|
+
const safeTitle = truncateToWidth(title, maxInner);
|
|
412
|
+
const top = frame(`${s.boxTL}${s.boxH} `) + t.emphasis(t.accent(safeTitle));
|
|
413
|
+
return [top, ...wrapped.map((line, i) => row(line, i === wrapped.length - 1))].join("\n");
|
|
438
414
|
}
|
|
439
415
|
var RESET = "\x1B[0m";
|
|
440
416
|
function ansi(code, str, enabled) {
|
|
@@ -455,7 +431,7 @@ function makeTokens(c) {
|
|
|
455
431
|
}
|
|
456
432
|
function signal(c, kind) {
|
|
457
433
|
const color2 = makeColors(c.color);
|
|
458
|
-
const raw =
|
|
434
|
+
const raw = { ok: "[ok]", warn: "[!]", error: "[x]", info: "[i]" }[kind];
|
|
459
435
|
if (kind === "ok") {
|
|
460
436
|
return color2.green(raw);
|
|
461
437
|
}
|
|
@@ -536,7 +512,6 @@ export {
|
|
|
536
512
|
clipToWidth,
|
|
537
513
|
padEndDisplay,
|
|
538
514
|
makeSymbols,
|
|
539
|
-
card,
|
|
540
515
|
sectionBox,
|
|
541
516
|
makeTokens,
|
|
542
517
|
signal,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
npmVersionCachePath
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-45X7T64Y.js";
|
|
4
4
|
|
|
5
5
|
// package.json
|
|
6
6
|
var name = "agent-work-loop";
|
|
7
|
-
var version = "0.6.
|
|
7
|
+
var version = "0.6.30";
|
|
8
8
|
|
|
9
9
|
// src/core/npm-registry.ts
|
|
10
10
|
import fs from "fs";
|
|
@@ -80,7 +80,7 @@ function readCachedLatestVersion() {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
// src/core/versions.ts
|
|
83
|
-
var UPDATE_HINT = "npm i -g agent-work-loop@latest \uB85C \uAC31\uC2E0\uD558\uC138\uC694.";
|
|
83
|
+
var UPDATE_HINT = "npm i -g agent-work-loop@latest \uB85C \uAC31\uC2E0\uD55C \uB4A4 awl update \uB97C \uC2E4\uD589\uD558\uC138\uC694.";
|
|
84
84
|
function parseSemver(version2) {
|
|
85
85
|
const m = /^(\d+)\.(\d+)\.(\d+)/.exec(version2);
|
|
86
86
|
if (!m) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveProjectRoot
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RAMHRXFX.js";
|
|
4
4
|
import {
|
|
5
5
|
caps,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from "./chunk-
|
|
6
|
+
makeColors,
|
|
7
|
+
sectionBox
|
|
8
|
+
} from "./chunk-45X7T64Y.js";
|
|
9
9
|
|
|
10
10
|
// src/commands/state.ts
|
|
11
11
|
import fs from "fs";
|
|
@@ -189,14 +189,14 @@ function requireRoot() {
|
|
|
189
189
|
function renderState(state, c) {
|
|
190
190
|
const color = makeColors(c.color);
|
|
191
191
|
if (Object.keys(state).length === 0) {
|
|
192
|
-
return
|
|
192
|
+
return sectionBox("\uD604\uC7AC \uC0C1\uD0DC", ["\uC0C1\uD0DC\uAC00 \uBE44\uC5B4 \uC788\uC2B5\uB2C8\uB2E4."], c);
|
|
193
193
|
}
|
|
194
194
|
const out = [];
|
|
195
195
|
for (const [k, v] of Object.entries(state)) {
|
|
196
196
|
const val = typeof v === "object" ? JSON.stringify(v) : String(v);
|
|
197
197
|
out.push(`${k.padEnd(14, " ")}${color.dim(val)}`);
|
|
198
198
|
}
|
|
199
|
-
return
|
|
199
|
+
return sectionBox("\uD604\uC7AC \uC0C1\uD0DC", out, c);
|
|
200
200
|
}
|
|
201
201
|
function runStateGet(opts) {
|
|
202
202
|
const state = loadState(requireRoot());
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
caps,
|
|
3
|
-
card,
|
|
4
3
|
engineDir,
|
|
5
4
|
globalRoot,
|
|
6
5
|
installedEngineVersion,
|
|
@@ -13,7 +12,7 @@ import {
|
|
|
13
12
|
sectionBox,
|
|
14
13
|
signal,
|
|
15
14
|
stringWidth
|
|
16
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-45X7T64Y.js";
|
|
17
16
|
|
|
18
17
|
// src/commands/init.ts
|
|
19
18
|
import fs from "fs";
|
|
@@ -312,7 +311,7 @@ function anyWorkspaceMemberHasTsconfig(cwd, pkg) {
|
|
|
312
311
|
}
|
|
313
312
|
return false;
|
|
314
313
|
}
|
|
315
|
-
function
|
|
314
|
+
function detectJsLanguage(cwd) {
|
|
316
315
|
if (exists(path.join(cwd, "tsconfig.json"))) {
|
|
317
316
|
return "typescript";
|
|
318
317
|
}
|
|
@@ -324,11 +323,25 @@ function detectLanguage(cwd) {
|
|
|
324
323
|
}
|
|
325
324
|
return "javascript";
|
|
326
325
|
}
|
|
327
|
-
if (exists(path.join(cwd, "pyproject.toml")) || exists(path.join(cwd, "setup.py")) || exists(path.join(cwd, "requirements.txt"))) {
|
|
328
|
-
return "python";
|
|
329
|
-
}
|
|
330
326
|
return null;
|
|
331
327
|
}
|
|
328
|
+
function hasPythonMarkers(cwd) {
|
|
329
|
+
return exists(path.join(cwd, "pyproject.toml")) || exists(path.join(cwd, "setup.py")) || exists(path.join(cwd, "requirements.txt"));
|
|
330
|
+
}
|
|
331
|
+
function detectLanguage(cwd) {
|
|
332
|
+
return detectJsLanguage(cwd) ?? (hasPythonMarkers(cwd) ? "python" : null);
|
|
333
|
+
}
|
|
334
|
+
function detectLanguages(cwd) {
|
|
335
|
+
const out = [];
|
|
336
|
+
const js = detectJsLanguage(cwd);
|
|
337
|
+
if (js) {
|
|
338
|
+
out.push(js);
|
|
339
|
+
}
|
|
340
|
+
if (hasPythonMarkers(cwd)) {
|
|
341
|
+
out.push("python");
|
|
342
|
+
}
|
|
343
|
+
return out;
|
|
344
|
+
}
|
|
332
345
|
function splitEnv(script) {
|
|
333
346
|
const env = {};
|
|
334
347
|
let rest = script.trim();
|
|
@@ -609,7 +622,7 @@ function nonInteractiveInputs(projectRoot) {
|
|
|
609
622
|
const skills = detected.claude || detected.codex ? detected : { claude: true, codex: false };
|
|
610
623
|
return {
|
|
611
624
|
project: path.basename(projectRoot),
|
|
612
|
-
mainLanguage:
|
|
625
|
+
mainLanguage: detectLanguages(projectRoot),
|
|
613
626
|
character: "",
|
|
614
627
|
verify: detectVerify(projectRoot),
|
|
615
628
|
skills
|
|
@@ -737,14 +750,17 @@ function renderResult(result, inputs, c) {
|
|
|
737
750
|
}
|
|
738
751
|
var LANG_OPTIONS = ["TypeScript", "JavaScript", "Python", "\uC9C1\uC811 \uC785\uB825"];
|
|
739
752
|
var LANG_VALUES = ["typescript", "javascript", "python", ""];
|
|
740
|
-
function
|
|
741
|
-
const detected =
|
|
742
|
-
|
|
743
|
-
|
|
753
|
+
function langDefaultIndices(projectRoot) {
|
|
754
|
+
const detected = detectLanguages(projectRoot);
|
|
755
|
+
if (detected.length === 0) {
|
|
756
|
+
return [0];
|
|
757
|
+
}
|
|
758
|
+
const indices = detected.map((lang) => LANG_VALUES.indexOf(lang)).filter((i) => i >= 0);
|
|
759
|
+
return indices.length > 0 ? indices : [0];
|
|
744
760
|
}
|
|
745
761
|
function buildScreens(projectRoot, hasGlobal, c) {
|
|
746
762
|
const project = path.basename(projectRoot);
|
|
747
|
-
const
|
|
763
|
+
const defLangIndices = langDefaultIndices(projectRoot);
|
|
748
764
|
const verify = detectVerify(projectRoot);
|
|
749
765
|
const agents = detectAgents(projectRoot);
|
|
750
766
|
const welcome = hasGlobal ? null : [
|
|
@@ -761,12 +777,13 @@ function buildScreens(projectRoot, hasGlobal, c) {
|
|
|
761
777
|
" \uADDC\uCE59\uACFC \uAD50\uD6C8\uC740 \uD504\uB85C\uC81D\uD2B8\uAC00 \uC544\uB2C8\uB77C \uB2F9\uC2E0\uC5D0\uAC8C \uC313\uC774\uACE0,",
|
|
762
778
|
" \uB4F1\uB85D\uB41C \uBAA8\uB4E0 \uD504\uB85C\uC81D\uD2B8\uC5D0\uC11C \uD568\uAED8 \uC4F0\uC785\uB2C8\uB2E4."
|
|
763
779
|
].join("\n");
|
|
780
|
+
const detectedLangLabels = defLangIndices.map((i) => LANG_OPTIONS[i] ?? "TypeScript").join(", ");
|
|
764
781
|
const langLines = [
|
|
765
|
-
`\uC790\uB3D9 \uAC10\uC9C0: ${
|
|
782
|
+
`\uC790\uB3D9 \uAC10\uC9C0: ${detectedLangLabels || "TypeScript"}`,
|
|
766
783
|
"",
|
|
767
|
-
"\
|
|
768
|
-
"\
|
|
769
|
-
"\uD0A4 \uC785\uB825\uC744 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD130\uBBF8\uB110\uC5D0\uC11C\uB294 \uBC88\uD638\uB97C \uC785\uB825\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4."
|
|
784
|
+
"\uC5EC\uB7EC \uAC1C\uB97C \uC4F0\uB294 \uD504\uB85C\uC81D\uD2B8\uBA74(\uC608: TypeScript \uD504\uB860\uD2B8 + Python \uBC31\uC5D4\uB4DC) \uC804\uBD80 \uACE0\uB974\uC138\uC694.",
|
|
785
|
+
"\u2191\u2193 \uB610\uB294 j/k \uB85C \uC774\uB3D9, Space \uB85C \uC120\uD0DD, Enter \uB85C \uD655\uC815\uD558\uC138\uC694.",
|
|
786
|
+
"\uD0A4 \uC785\uB825\uC744 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD130\uBBF8\uB110\uC5D0\uC11C\uB294 \uBC88\uD638\uB97C \uC27C\uD45C\uB85C \uC785\uB825\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4."
|
|
770
787
|
];
|
|
771
788
|
return {
|
|
772
789
|
welcome,
|
|
@@ -905,21 +922,19 @@ async function interactiveInputs(projectRoot, hasGlobal, c) {
|
|
|
905
922
|
${screens.lang}
|
|
906
923
|
|
|
907
924
|
`);
|
|
908
|
-
const
|
|
925
|
+
const defaultLangChecked = langDefaultIndices(projectRoot);
|
|
926
|
+
const rawLanguage = useRawMode ? await runInteractiveSelect(LANG_OPTIONS, 0, true, c, defaultLangChecked, {
|
|
909
927
|
title: "\uC8FC \uC5B8\uC5B4",
|
|
910
|
-
hint: "\u2191\u2193 \uB610\uB294 j/k \uC774\uB3D9 \xB7
|
|
928
|
+
hint: "\u2191\u2193 \uB610\uB294 j/k \uC774\uB3D9 \xB7 Space \uC120\uD0DD \xB7 Enter \uD655\uC815 \xB7 Esc \uAE30\uBCF8\uAC12 \uC720\uC9C0"
|
|
911
929
|
}) : null;
|
|
912
|
-
const
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
let mainLanguage = LANG_VALUES[langIdx] ?? "";
|
|
921
|
-
if (langIdx === LANG_OPTIONS.length - 1) {
|
|
922
|
-
mainLanguage = (await ask(prompt(), " \uC8FC \uC5B8\uC5B4\uB97C \uC785\uB825\uD558\uC138\uC694: ")).trim();
|
|
930
|
+
const langChecked = rawLanguage?.checked ?? (useRawMode ? defaultLangChecked : await selectMulti(prompt(), LANG_OPTIONS, defaultLangChecked, c, false, "\uC8FC \uC5B8\uC5B4"));
|
|
931
|
+
const manualLangIdx = LANG_OPTIONS.length - 1;
|
|
932
|
+
const mainLanguage = langChecked.filter((i) => i !== manualLangIdx).map((i) => LANG_VALUES[i]).filter((v) => typeof v === "string" && v !== "");
|
|
933
|
+
if (langChecked.includes(manualLangIdx)) {
|
|
934
|
+
const typed = (await ask(prompt(), " \uC8FC \uC5B8\uC5B4\uB97C \uC785\uB825\uD558\uC138\uC694: ")).trim();
|
|
935
|
+
if (typed) {
|
|
936
|
+
mainLanguage.push(typed);
|
|
937
|
+
}
|
|
923
938
|
}
|
|
924
939
|
const rootVerify = detectVerify(projectRoot);
|
|
925
940
|
const located = await promptVerifyLocation(
|
|
@@ -1001,7 +1016,7 @@ async function handleExistingConfig(rl, projectRoot, c, now) {
|
|
|
1001
1016
|
process.stdout.write("\n .awl/config.json \uC774 \uC774\uBBF8 \uC788\uC2B5\uB2C8\uB2E4. \uD300\uC6D0\uC774 \uC124\uC815\uD574\uB450\uC5C8\uAD70\uC694.\n\n");
|
|
1002
1017
|
process.stdout.write(` \uD504\uB85C\uC81D\uD2B8 ${config?.project ?? "(\uC5C6\uC74C)"}
|
|
1003
1018
|
`);
|
|
1004
|
-
process.stdout.write(` \uC8FC \uC5B8\uC5B4 ${config?.mainLanguage
|
|
1019
|
+
process.stdout.write(` \uC8FC \uC5B8\uC5B4 ${config?.mainLanguage?.join(", ") || "(\uC5C6\uC74C)"}
|
|
1005
1020
|
`);
|
|
1006
1021
|
process.stdout.write(` \uC131\uACA9 ${config?.character || "(\uC5C6\uC74C)"}
|
|
1007
1022
|
`);
|
|
@@ -1019,7 +1034,7 @@ async function handleExistingConfig(rl, projectRoot, c, now) {
|
|
|
1019
1034
|
process.stdout.write(" \uC774 \uC124\uC815\uC744 \uADF8\uB300\uB85C \uC4F0\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?\n\n");
|
|
1020
1035
|
const options = ["\uADF8\uB300\uB85C \uC4F4\uB2E4", "\uAC80\uC99D \uBA85\uB839\uC5B4\uB9CC \uACE0\uCE5C\uB2E4", "\uCC98\uC74C\uBD80\uD130 \uB2E4\uC2DC"];
|
|
1021
1036
|
process.stdout.write(
|
|
1022
|
-
`${
|
|
1037
|
+
`${sectionBox(
|
|
1023
1038
|
"\uAE30\uC874 \uC124\uC815",
|
|
1024
1039
|
options.map((option, i) => `${i + 1}. ${option}`),
|
|
1025
1040
|
c
|
|
@@ -1057,7 +1072,7 @@ async function handleExistingConfig(rl, projectRoot, c, now) {
|
|
|
1057
1072
|
}
|
|
1058
1073
|
const merged = {
|
|
1059
1074
|
project: config?.project ?? path.basename(projectRoot),
|
|
1060
|
-
mainLanguage: config?.mainLanguage ??
|
|
1075
|
+
mainLanguage: config?.mainLanguage ?? [],
|
|
1061
1076
|
character: config?.character ?? "",
|
|
1062
1077
|
verify,
|
|
1063
1078
|
skills: { claude: false, codex: false }
|
|
@@ -1106,6 +1121,27 @@ function registeredProjectPaths() {
|
|
|
1106
1121
|
return /* @__PURE__ */ new Set();
|
|
1107
1122
|
}
|
|
1108
1123
|
}
|
|
1124
|
+
function listRegisteredProjects() {
|
|
1125
|
+
try {
|
|
1126
|
+
const raw = JSON.parse(fs.readFileSync(projectsFile(), "utf8"));
|
|
1127
|
+
if (!Array.isArray(raw)) {
|
|
1128
|
+
return [];
|
|
1129
|
+
}
|
|
1130
|
+
const out = [];
|
|
1131
|
+
for (const entry of raw) {
|
|
1132
|
+
if (entry && typeof entry === "object" && typeof entry.path === "string") {
|
|
1133
|
+
const e = entry;
|
|
1134
|
+
out.push({
|
|
1135
|
+
name: typeof e.name === "string" ? e.name : path.basename(e.path),
|
|
1136
|
+
path: e.path
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
return out;
|
|
1141
|
+
} catch {
|
|
1142
|
+
return [];
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1109
1145
|
function excludeRegisteredProjects(candidates, registered) {
|
|
1110
1146
|
if (registered.size === 0) {
|
|
1111
1147
|
return candidates;
|
|
@@ -1242,6 +1278,7 @@ ${renderResult(result, inputs, c)}
|
|
|
1242
1278
|
export {
|
|
1243
1279
|
scanGitProjects,
|
|
1244
1280
|
detectLanguage,
|
|
1281
|
+
detectLanguages,
|
|
1245
1282
|
splitEnv,
|
|
1246
1283
|
detectVerify,
|
|
1247
1284
|
detectWorkspacePackages,
|
|
@@ -1277,6 +1314,7 @@ export {
|
|
|
1277
1314
|
applyVerifyCwd,
|
|
1278
1315
|
resolveProjectChoice,
|
|
1279
1316
|
registeredProjectPaths,
|
|
1317
|
+
listRegisteredProjects,
|
|
1280
1318
|
excludeRegisteredProjects,
|
|
1281
1319
|
runInit
|
|
1282
1320
|
};
|
|
@@ -3,23 +3,23 @@ import {
|
|
|
3
3
|
getLatestVersionCached,
|
|
4
4
|
name,
|
|
5
5
|
version
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-7WDDWO2B.js";
|
|
7
7
|
import {
|
|
8
8
|
resolveProjectRoot
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-RAMHRXFX.js";
|
|
10
10
|
import {
|
|
11
11
|
packageEngineDir,
|
|
12
12
|
skillsVersionPath
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-AYFHV27J.js";
|
|
14
14
|
import {
|
|
15
15
|
caps,
|
|
16
|
-
card,
|
|
17
16
|
installedEngineVersion,
|
|
18
17
|
makeColors,
|
|
19
18
|
makeSymbols,
|
|
20
19
|
makeTokens,
|
|
20
|
+
sectionBox,
|
|
21
21
|
signal
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-45X7T64Y.js";
|
|
23
23
|
|
|
24
24
|
// src/commands/version-check.ts
|
|
25
25
|
import fs from "fs";
|
|
@@ -67,14 +67,14 @@ function renderVersionCheck(result, c) {
|
|
|
67
67
|
const s = makeSymbols(c);
|
|
68
68
|
const t = makeTokens(c);
|
|
69
69
|
if (result.ok) {
|
|
70
|
-
return
|
|
70
|
+
return sectionBox("\uBC84\uC804 \uD655\uC778", [`${signal(c, "ok")} \uBC84\uC804\uC774 \uC804\uBD80 \uC77C\uCE58\uD569\uB2C8\uB2E4.`], c);
|
|
71
71
|
}
|
|
72
72
|
const out = [];
|
|
73
73
|
for (const m of result.mismatches) {
|
|
74
74
|
out.push(`${signal(c, "warn")} ${m.kind}: ${t.emphasis(m.a)} / ${t.emphasis(m.b)}`);
|
|
75
75
|
out.push(`${s.lastBranch} ${color.dim(m.hint)}`);
|
|
76
76
|
}
|
|
77
|
-
return
|
|
77
|
+
return sectionBox(`\uBC84\uC804 \uBD88\uC77C\uCE58 ${result.mismatches.length}\uAC74`, out, c);
|
|
78
78
|
}
|
|
79
79
|
async function runVersionCheck(opts) {
|
|
80
80
|
const projectRoot = resolveProjectRoot();
|