@sentry/warden 0.1.0 → 0.1.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/.claude/skills/warden-skill/SKILL.md +0 -24
- package/.claude/skills/warden-skill/references/config-schema.md +0 -17
- package/dist/action/cli/output/icons.d.ts +4 -0
- package/dist/action/cli/output/icons.d.ts.map +1 -1
- package/dist/action/cli/output/ink-runner.d.ts +20 -0
- package/dist/action/cli/output/ink-runner.d.ts.map +1 -1
- package/dist/cli/output/icons.d.ts +4 -0
- package/dist/cli/output/icons.d.ts.map +1 -1
- package/dist/cli/output/icons.js +4 -0
- package/dist/cli/output/icons.js.map +1 -1
- package/dist/cli/output/ink-runner.d.ts +20 -0
- package/dist/cli/output/ink-runner.d.ts.map +1 -1
- package/dist/cli/output/ink-runner.js +53 -19
- package/dist/cli/output/ink-runner.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/output/icons.ts +6 -0
- package/src/cli/output/ink-runner.tsx +69 -40
|
@@ -175,30 +175,6 @@ remote = "getsentry/skills@abc123"
|
|
|
175
175
|
|
|
176
176
|
**Cache TTL:** 24 hours for unpinned refs (override with `WARDEN_SKILL_CACHE_TTL` in seconds)
|
|
177
177
|
|
|
178
|
-
**Inline skill in warden.toml:**
|
|
179
|
-
|
|
180
|
-
```toml
|
|
181
|
-
[[skills]]
|
|
182
|
-
name = "custom-check"
|
|
183
|
-
description = "Check for TODO comments"
|
|
184
|
-
prompt = """
|
|
185
|
-
Find TODO comments that have been in the code for too long.
|
|
186
|
-
Report as low severity findings.
|
|
187
|
-
"""
|
|
188
|
-
|
|
189
|
-
[skills.tools]
|
|
190
|
-
allowed = ["Read", "Grep", "Glob"]
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
## Built-in Skills
|
|
194
|
-
|
|
195
|
-
| Skill | Purpose |
|
|
196
|
-
|-------|---------|
|
|
197
|
-
| `find-bugs` | Logical/functional bugs, null handling, async issues |
|
|
198
|
-
| `security-review` | Injection, auth, CSRF, crypto, race conditions |
|
|
199
|
-
| `code-simplifier` | Readability, consistency, redundancy removal |
|
|
200
|
-
| `performance-review` | N+1 queries, blocking I/O, memory leaks |
|
|
201
|
-
|
|
202
178
|
## Common Patterns
|
|
203
179
|
|
|
204
180
|
**Strict security on critical files:**
|
|
@@ -7,7 +7,6 @@ version = 1 # Required, must be 1
|
|
|
7
7
|
|
|
8
8
|
[defaults] # Optional, inherited by all triggers
|
|
9
9
|
[[triggers]] # Required, array of trigger configs
|
|
10
|
-
[[skills]] # Optional, inline skill definitions
|
|
11
10
|
```
|
|
12
11
|
|
|
13
12
|
## Defaults Section
|
|
@@ -81,22 +80,6 @@ fixBranchPrefix = "security-fix" # Branch name prefix
|
|
|
81
80
|
**Actions (for non-schedule):**
|
|
82
81
|
- `opened`, `synchronize`, `reopened`, `closed`
|
|
83
82
|
|
|
84
|
-
## Skills Section (Inline Skills)
|
|
85
|
-
|
|
86
|
-
```toml
|
|
87
|
-
[[skills]]
|
|
88
|
-
name = "custom-skill"
|
|
89
|
-
description = "What this skill checks"
|
|
90
|
-
prompt = """
|
|
91
|
-
Analysis instructions here.
|
|
92
|
-
Look for specific issues.
|
|
93
|
-
"""
|
|
94
|
-
|
|
95
|
-
[skills.tools]
|
|
96
|
-
allowed = ["Read", "Grep", "Glob"] # Whitelist tools
|
|
97
|
-
denied = ["Write", "Edit", "Bash"] # Blacklist tools (optional)
|
|
98
|
-
```
|
|
99
|
-
|
|
100
83
|
## Severity Values
|
|
101
84
|
|
|
102
85
|
Used in `failOn` and `commentOn`:
|
|
@@ -8,4 +8,8 @@ export declare const ICON_CHECK = "\u2713";
|
|
|
8
8
|
export declare const ICON_SKIPPED = "\u2193";
|
|
9
9
|
/** Braille spinner frames for loading animation */
|
|
10
10
|
export declare const SPINNER_FRAMES: string[];
|
|
11
|
+
/** Circle for pending states */
|
|
12
|
+
export declare const ICON_PENDING = "\u25CB";
|
|
13
|
+
/** X mark for error states */
|
|
14
|
+
export declare const ICON_ERROR = "\u2717";
|
|
11
15
|
//# sourceMappingURL=icons.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["file:///home/runner/work/warden/warden/src/cli/output/icons.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8CAA8C;AAC9C,eAAO,MAAM,UAAU,WAAM,CAAC;AAE9B,oCAAoC;AACpC,eAAO,MAAM,YAAY,WAAM,CAAC;AAEhC,mDAAmD;AACnD,eAAO,MAAM,cAAc,UAAuG,CAAC"}
|
|
1
|
+
{"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["file:///home/runner/work/warden/warden/src/cli/output/icons.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8CAA8C;AAC9C,eAAO,MAAM,UAAU,WAAM,CAAC;AAE9B,oCAAoC;AACpC,eAAO,MAAM,YAAY,WAAM,CAAC;AAEhC,mDAAmD;AACnD,eAAO,MAAM,cAAc,UAAuG,CAAC;AAEnI,gCAAgC;AAChC,eAAO,MAAM,YAAY,WAAW,CAAC;AAErC,8BAA8B;AAC9B,eAAO,MAAM,UAAU,WAAW,CAAC"}
|
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Ink-based skill runner with real-time progress display.
|
|
3
|
+
*
|
|
4
|
+
* ## Ink Rendering Constraints
|
|
5
|
+
*
|
|
6
|
+
* This file uses Ink (React for CLIs) which has specific constraints that,
|
|
7
|
+
* if violated, cause duplicate output lines or corrupted display:
|
|
8
|
+
*
|
|
9
|
+
* 1. **Single Static component**: Ink's Static uses `position: 'absolute'`.
|
|
10
|
+
* Multiple Static components cause layout conflicts. We print the header
|
|
11
|
+
* before Ink starts to avoid needing a second Static.
|
|
12
|
+
*
|
|
13
|
+
* 2. **Stable item references**: Static tracks items by reference equality.
|
|
14
|
+
* Never wrap items in new objects (e.g., `{ type: 'skill', skill }`) on
|
|
15
|
+
* each render. Pass the original objects directly.
|
|
16
|
+
*
|
|
17
|
+
* 3. **Batched updates**: Rapid consecutive rerender() calls cause duplicate
|
|
18
|
+
* output. The updateUI() function batches updates using setImmediate().
|
|
19
|
+
*
|
|
20
|
+
* 4. **No direct writes to stderr**: Writing to process.stderr while Ink is
|
|
21
|
+
* running corrupts cursor tracking. The onLargePrompt/onPromptSize callbacks
|
|
22
|
+
* are exceptions that may cause minor display glitches in edge cases.
|
|
3
23
|
*/
|
|
4
24
|
import { type SkillTaskOptions, type SkillTaskResult, type RunTasksOptions } from './tasks.js';
|
|
5
25
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ink-runner.d.ts","sourceRoot":"","sources":["file:///home/runner/work/warden/warden/src/cli/output/ink-runner.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ink-runner.d.ts","sourceRoot":"","sources":["file:///home/runner/work/warden/warden/src/cli/output/ink-runner.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,eAAe,EAIrB,MAAM,YAAY,CAAC;AAoKpB;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,gBAAgB,EAAE,EACzB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,eAAe,EAAE,CAAC,CAiK5B"}
|
|
@@ -8,4 +8,8 @@ export declare const ICON_CHECK = "\u2713";
|
|
|
8
8
|
export declare const ICON_SKIPPED = "\u2193";
|
|
9
9
|
/** Braille spinner frames for loading animation */
|
|
10
10
|
export declare const SPINNER_FRAMES: string[];
|
|
11
|
+
/** Circle for pending states */
|
|
12
|
+
export declare const ICON_PENDING = "\u25CB";
|
|
13
|
+
/** X mark for error states */
|
|
14
|
+
export declare const ICON_ERROR = "\u2717";
|
|
11
15
|
//# sourceMappingURL=icons.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../../src/cli/output/icons.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8CAA8C;AAC9C,eAAO,MAAM,UAAU,WAAM,CAAC;AAE9B,oCAAoC;AACpC,eAAO,MAAM,YAAY,WAAM,CAAC;AAEhC,mDAAmD;AACnD,eAAO,MAAM,cAAc,UAAuG,CAAC"}
|
|
1
|
+
{"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../../src/cli/output/icons.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8CAA8C;AAC9C,eAAO,MAAM,UAAU,WAAM,CAAC;AAE9B,oCAAoC;AACpC,eAAO,MAAM,YAAY,WAAM,CAAC;AAEhC,mDAAmD;AACnD,eAAO,MAAM,cAAc,UAAuG,CAAC;AAEnI,gCAAgC;AAChC,eAAO,MAAM,YAAY,WAAW,CAAC;AAErC,8BAA8B;AAC9B,eAAO,MAAM,UAAU,WAAW,CAAC"}
|
package/dist/cli/output/icons.js
CHANGED
|
@@ -8,4 +8,8 @@ export const ICON_CHECK = '✓'; // U+2713 CHECK MARK
|
|
|
8
8
|
export const ICON_SKIPPED = '↓'; // U+2193 DOWNWARDS ARROW
|
|
9
9
|
/** Braille spinner frames for loading animation */
|
|
10
10
|
export const SPINNER_FRAMES = ['\u280B', '\u2819', '\u2839', '\u2838', '\u283C', '\u2834', '\u2826', '\u2827', '\u2807', '\u280F'];
|
|
11
|
+
/** Circle for pending states */
|
|
12
|
+
export const ICON_PENDING = '\u25CB'; // ○ WHITE CIRCLE
|
|
13
|
+
/** X mark for error states */
|
|
14
|
+
export const ICON_ERROR = '\u2717'; // ✗ BALLOT X
|
|
11
15
|
//# sourceMappingURL=icons.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icons.js","sourceRoot":"","sources":["../../../src/cli/output/icons.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8CAA8C;AAC9C,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,CAAC,CAAC,oBAAoB;AAEnD,oCAAoC;AACpC,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAC,CAAC,yBAAyB;AAE1D,mDAAmD;AACnD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"icons.js","sourceRoot":"","sources":["../../../src/cli/output/icons.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,8CAA8C;AAC9C,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,CAAC,CAAC,oBAAoB;AAEnD,oCAAoC;AACpC,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAC,CAAC,yBAAyB;AAE1D,mDAAmD;AACnD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAEnI,gCAAgC;AAChC,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAC,CAAC,iBAAiB;AAEvD,8BAA8B;AAC9B,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,CAAC,aAAa"}
|
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Ink-based skill runner with real-time progress display.
|
|
3
|
+
*
|
|
4
|
+
* ## Ink Rendering Constraints
|
|
5
|
+
*
|
|
6
|
+
* This file uses Ink (React for CLIs) which has specific constraints that,
|
|
7
|
+
* if violated, cause duplicate output lines or corrupted display:
|
|
8
|
+
*
|
|
9
|
+
* 1. **Single Static component**: Ink's Static uses `position: 'absolute'`.
|
|
10
|
+
* Multiple Static components cause layout conflicts. We print the header
|
|
11
|
+
* before Ink starts to avoid needing a second Static.
|
|
12
|
+
*
|
|
13
|
+
* 2. **Stable item references**: Static tracks items by reference equality.
|
|
14
|
+
* Never wrap items in new objects (e.g., `{ type: 'skill', skill }`) on
|
|
15
|
+
* each render. Pass the original objects directly.
|
|
16
|
+
*
|
|
17
|
+
* 3. **Batched updates**: Rapid consecutive rerender() calls cause duplicate
|
|
18
|
+
* output. The updateUI() function batches updates using setImmediate().
|
|
19
|
+
*
|
|
20
|
+
* 4. **No direct writes to stderr**: Writing to process.stderr while Ink is
|
|
21
|
+
* running corrupts cursor tracking. The onLargePrompt/onPromptSize callbacks
|
|
22
|
+
* are exceptions that may cause minor display glitches in edge cases.
|
|
3
23
|
*/
|
|
4
24
|
import { type SkillTaskOptions, type SkillTaskResult, type RunTasksOptions } from './tasks.js';
|
|
5
25
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ink-runner.d.ts","sourceRoot":"","sources":["../../../src/cli/output/ink-runner.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ink-runner.d.ts","sourceRoot":"","sources":["../../../src/cli/output/ink-runner.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,eAAe,EAIrB,MAAM,YAAY,CAAC;AAoKpB;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,gBAAgB,EAAE,EACzB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,eAAe,EAAE,CAAC,CAiK5B"}
|
|
@@ -1,13 +1,33 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
/**
|
|
3
3
|
* Ink-based skill runner with real-time progress display.
|
|
4
|
+
*
|
|
5
|
+
* ## Ink Rendering Constraints
|
|
6
|
+
*
|
|
7
|
+
* This file uses Ink (React for CLIs) which has specific constraints that,
|
|
8
|
+
* if violated, cause duplicate output lines or corrupted display:
|
|
9
|
+
*
|
|
10
|
+
* 1. **Single Static component**: Ink's Static uses `position: 'absolute'`.
|
|
11
|
+
* Multiple Static components cause layout conflicts. We print the header
|
|
12
|
+
* before Ink starts to avoid needing a second Static.
|
|
13
|
+
*
|
|
14
|
+
* 2. **Stable item references**: Static tracks items by reference equality.
|
|
15
|
+
* Never wrap items in new objects (e.g., `{ type: 'skill', skill }`) on
|
|
16
|
+
* each render. Pass the original objects directly.
|
|
17
|
+
*
|
|
18
|
+
* 3. **Batched updates**: Rapid consecutive rerender() calls cause duplicate
|
|
19
|
+
* output. The updateUI() function batches updates using setImmediate().
|
|
20
|
+
*
|
|
21
|
+
* 4. **No direct writes to stderr**: Writing to process.stderr while Ink is
|
|
22
|
+
* running corrupts cursor tracking. The onLargePrompt/onPromptSize callbacks
|
|
23
|
+
* are exceptions that may cause minor display glitches in edge cases.
|
|
4
24
|
*/
|
|
5
25
|
import { useState, useEffect } from 'react';
|
|
6
26
|
import { render, Box, Text, Static } from 'ink';
|
|
7
27
|
import { runSkillTask, } from './tasks.js';
|
|
8
28
|
import { formatDuration, truncate, countBySeverity, formatSeverityDot } from './formatters.js';
|
|
9
29
|
import { Verbosity } from './verbosity.js';
|
|
10
|
-
import { ICON_CHECK, ICON_SKIPPED, SPINNER_FRAMES } from './icons.js';
|
|
30
|
+
import { ICON_CHECK, ICON_SKIPPED, ICON_PENDING, ICON_ERROR, SPINNER_FRAMES } from './icons.js';
|
|
11
31
|
import figures from 'figures';
|
|
12
32
|
function Spinner() {
|
|
13
33
|
const [frame, setFrame] = useState(0);
|
|
@@ -37,7 +57,7 @@ function CompletedSkill({ skill }) {
|
|
|
37
57
|
return (_jsxs(Box, { children: [_jsx(Text, { color: "yellow", children: ICON_SKIPPED }), _jsxs(Text, { children: [" ", skill.displayName] }), _jsx(Text, { dimColor: true, children: " [skipped]" })] }));
|
|
38
58
|
}
|
|
39
59
|
if (skill.status === 'error') {
|
|
40
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: "red", children:
|
|
60
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: "red", children: ICON_ERROR }), _jsxs(Text, { children: [" ", skill.displayName] }), duration && _jsxs(Text, { dimColor: true, children: [" [", duration, "]"] })] }), skill.error && _jsxs(Text, { color: "red", children: [" Error: ", skill.error] })] }));
|
|
41
61
|
}
|
|
42
62
|
return (_jsxs(Box, { children: [_jsx(Text, { color: "green", children: ICON_CHECK }), _jsxs(Text, { children: [" ", skill.displayName] }), duration && _jsxs(Text, { dimColor: true, children: [" [", duration, "]"] })] }));
|
|
43
63
|
}
|
|
@@ -45,22 +65,21 @@ function RunningSkill({ skill }) {
|
|
|
45
65
|
const visibleFiles = skill.files.filter((f) => f.status !== 'pending');
|
|
46
66
|
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Spinner, {}), _jsxs(Text, { children: [" ", skill.displayName] })] }), visibleFiles.map((file) => (_jsx(Box, { marginLeft: 2, children: _jsx(FileProgress, { file: file }) }, file.filename)))] }));
|
|
47
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Renders the skill execution UI.
|
|
70
|
+
*
|
|
71
|
+
* IMPORTANT: Ink's Static component tracks items by reference equality.
|
|
72
|
+
* Items passed to Static must have stable references across renders.
|
|
73
|
+
* Creating new wrapper objects causes Static to mishandle its internal
|
|
74
|
+
* state, resulting in duplicate output lines.
|
|
75
|
+
*
|
|
76
|
+
* We use a SINGLE Static component to avoid layout conflicts from multiple
|
|
77
|
+
* absolutely-positioned Static containers.
|
|
78
|
+
*/
|
|
48
79
|
function SkillRunner({ skills, completedItems }) {
|
|
49
80
|
const running = skills.filter((s) => s.status === 'running');
|
|
50
81
|
const pending = skills.filter((s) => s.status === 'pending');
|
|
51
|
-
|
|
52
|
-
const staticItems = [
|
|
53
|
-
{ type: 'header' },
|
|
54
|
-
...completedItems.map((skill) => ({ type: 'skill', skill })),
|
|
55
|
-
];
|
|
56
|
-
return (_jsxs(_Fragment, { children: [_jsx(Static, { items: staticItems, children: (item) => {
|
|
57
|
-
switch (item.type) {
|
|
58
|
-
case 'header':
|
|
59
|
-
return (_jsx(Text, { bold: true, children: "SKILLS" }, "header"));
|
|
60
|
-
case 'skill':
|
|
61
|
-
return _jsx(CompletedSkill, { skill: item.skill }, item.skill.name);
|
|
62
|
-
}
|
|
63
|
-
} }), _jsxs(Box, { flexDirection: "column", children: [running.map((skill) => (_jsx(RunningSkill, { skill: skill }, skill.name))), pending.map((skill) => (_jsxs(Text, { dimColor: true, children: ['\u25CB', " ", skill.displayName] }, skill.name)))] })] }));
|
|
82
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Static, { items: completedItems, children: (skill) => _jsx(CompletedSkill, { skill: skill }, skill.name) }), running.map((skill) => (_jsx(RunningSkill, { skill: skill }, skill.name))), pending.map((skill) => (_jsxs(Text, { dimColor: true, children: [ICON_PENDING, " ", skill.displayName] }, skill.name)))] }));
|
|
64
83
|
}
|
|
65
84
|
/** No-op callbacks for quiet mode. */
|
|
66
85
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
@@ -91,10 +110,24 @@ export async function runSkillTasksWithInk(tasks, options) {
|
|
|
91
110
|
const skillStates = [];
|
|
92
111
|
const completedItems = [];
|
|
93
112
|
const completedNames = new Set();
|
|
113
|
+
// Print header before Ink starts - this avoids multiple Static components
|
|
114
|
+
// which can cause layout conflicts due to absolute positioning
|
|
115
|
+
process.stderr.write('\x1b[1mSKILLS\x1b[0m\n');
|
|
94
116
|
// Create Ink instance
|
|
95
117
|
const { rerender, unmount } = render(_jsx(SkillRunner, { skills: skillStates, completedItems: completedItems }), { stdout: process.stderr });
|
|
118
|
+
// Batch UI updates to prevent rapid consecutive rerenders that cause duplicate lines.
|
|
119
|
+
// Without batching, multiple callbacks firing in quick succession (e.g., 5 files
|
|
120
|
+
// starting simultaneously) trigger 5 immediate rerenders, which Ink cannot
|
|
121
|
+
// process correctly, resulting in the same line appearing multiple times.
|
|
122
|
+
let updatePending = false;
|
|
96
123
|
const updateUI = () => {
|
|
97
|
-
|
|
124
|
+
if (updatePending)
|
|
125
|
+
return;
|
|
126
|
+
updatePending = true;
|
|
127
|
+
setImmediate(() => {
|
|
128
|
+
updatePending = false;
|
|
129
|
+
rerender(_jsx(SkillRunner, { skills: [...skillStates], completedItems: [...completedItems] }));
|
|
130
|
+
});
|
|
98
131
|
};
|
|
99
132
|
// Callbacks to update state
|
|
100
133
|
const callbacks = {
|
|
@@ -171,13 +204,14 @@ export async function runSkillTasksWithInk(tasks, options) {
|
|
|
171
204
|
}
|
|
172
205
|
updateUI();
|
|
173
206
|
},
|
|
174
|
-
//
|
|
207
|
+
// CAUTION: Direct stderr writes while Ink is running can cause display glitches.
|
|
208
|
+
// These callbacks are rare (large prompts, debug mode) so the tradeoff is acceptable.
|
|
209
|
+
// If these cause issues, consider queueing messages and printing after unmount().
|
|
175
210
|
onLargePrompt: (_skillName, filename, lineRange, chars, estimatedTokens) => {
|
|
176
211
|
const location = `${filename}:${lineRange}`;
|
|
177
212
|
const size = `${Math.round(chars / 1000)}k chars (~${Math.round(estimatedTokens / 1000)}k tokens)`;
|
|
178
213
|
process.stderr.write(`\x1b[33m${figures.warning}\x1b[0m Large prompt for ${location}: ${size}\n`);
|
|
179
214
|
},
|
|
180
|
-
// Debug mode: show prompt sizes
|
|
181
215
|
onPromptSize: verbosity >= Verbosity.Debug
|
|
182
216
|
? (_skillName, filename, lineRange, systemChars, userChars, totalChars, estimatedTokens) => {
|
|
183
217
|
const location = `${filename}:${lineRange}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ink-runner.js","sourceRoot":"","sources":["../../../src/cli/output/ink-runner.tsx"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"ink-runner.js","sourceRoot":"","sources":["../../../src/cli/output/ink-runner.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/cli/output/icons.ts
CHANGED
|
@@ -11,3 +11,9 @@ export const ICON_SKIPPED = '↓'; // U+2193 DOWNWARDS ARROW
|
|
|
11
11
|
|
|
12
12
|
/** Braille spinner frames for loading animation */
|
|
13
13
|
export const SPINNER_FRAMES = ['\u280B', '\u2819', '\u2839', '\u2838', '\u283C', '\u2834', '\u2826', '\u2827', '\u2807', '\u280F'];
|
|
14
|
+
|
|
15
|
+
/** Circle for pending states */
|
|
16
|
+
export const ICON_PENDING = '\u25CB'; // ○ WHITE CIRCLE
|
|
17
|
+
|
|
18
|
+
/** X mark for error states */
|
|
19
|
+
export const ICON_ERROR = '\u2717'; // ✗ BALLOT X
|
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Ink-based skill runner with real-time progress display.
|
|
3
|
+
*
|
|
4
|
+
* ## Ink Rendering Constraints
|
|
5
|
+
*
|
|
6
|
+
* This file uses Ink (React for CLIs) which has specific constraints that,
|
|
7
|
+
* if violated, cause duplicate output lines or corrupted display:
|
|
8
|
+
*
|
|
9
|
+
* 1. **Single Static component**: Ink's Static uses `position: 'absolute'`.
|
|
10
|
+
* Multiple Static components cause layout conflicts. We print the header
|
|
11
|
+
* before Ink starts to avoid needing a second Static.
|
|
12
|
+
*
|
|
13
|
+
* 2. **Stable item references**: Static tracks items by reference equality.
|
|
14
|
+
* Never wrap items in new objects (e.g., `{ type: 'skill', skill }`) on
|
|
15
|
+
* each render. Pass the original objects directly.
|
|
16
|
+
*
|
|
17
|
+
* 3. **Batched updates**: Rapid consecutive rerender() calls cause duplicate
|
|
18
|
+
* output. The updateUI() function batches updates using setImmediate().
|
|
19
|
+
*
|
|
20
|
+
* 4. **No direct writes to stderr**: Writing to process.stderr while Ink is
|
|
21
|
+
* running corrupts cursor tracking. The onLargePrompt/onPromptSize callbacks
|
|
22
|
+
* are exceptions that may cause minor display glitches in edge cases.
|
|
3
23
|
*/
|
|
4
24
|
|
|
5
25
|
import React, { useState, useEffect } from 'react';
|
|
@@ -15,11 +35,9 @@ import {
|
|
|
15
35
|
} from './tasks.js';
|
|
16
36
|
import { formatDuration, truncate, countBySeverity, formatSeverityDot } from './formatters.js';
|
|
17
37
|
import { Verbosity } from './verbosity.js';
|
|
18
|
-
import { ICON_CHECK, ICON_SKIPPED, SPINNER_FRAMES } from './icons.js';
|
|
38
|
+
import { ICON_CHECK, ICON_SKIPPED, ICON_PENDING, ICON_ERROR, SPINNER_FRAMES } from './icons.js';
|
|
19
39
|
import figures from 'figures';
|
|
20
40
|
|
|
21
|
-
type StaticItem = { type: 'header' } | { type: 'skill'; skill: SkillState };
|
|
22
|
-
|
|
23
41
|
interface SkillRunnerProps {
|
|
24
42
|
skills: SkillState[];
|
|
25
43
|
completedItems: SkillState[];
|
|
@@ -91,7 +109,7 @@ function CompletedSkill({ skill }: { skill: SkillState }): React.ReactElement {
|
|
|
91
109
|
return (
|
|
92
110
|
<Box flexDirection="column">
|
|
93
111
|
<Box>
|
|
94
|
-
<Text color="red">{
|
|
112
|
+
<Text color="red">{ICON_ERROR}</Text>
|
|
95
113
|
<Text> {skill.displayName}</Text>
|
|
96
114
|
{duration && <Text dimColor> [{duration}]</Text>}
|
|
97
115
|
</Box>
|
|
@@ -127,46 +145,42 @@ function RunningSkill({ skill }: { skill: SkillState }): React.ReactElement {
|
|
|
127
145
|
);
|
|
128
146
|
}
|
|
129
147
|
|
|
148
|
+
/**
|
|
149
|
+
* Renders the skill execution UI.
|
|
150
|
+
*
|
|
151
|
+
* IMPORTANT: Ink's Static component tracks items by reference equality.
|
|
152
|
+
* Items passed to Static must have stable references across renders.
|
|
153
|
+
* Creating new wrapper objects causes Static to mishandle its internal
|
|
154
|
+
* state, resulting in duplicate output lines.
|
|
155
|
+
*
|
|
156
|
+
* We use a SINGLE Static component to avoid layout conflicts from multiple
|
|
157
|
+
* absolutely-positioned Static containers.
|
|
158
|
+
*/
|
|
130
159
|
function SkillRunner({ skills, completedItems }: SkillRunnerProps): React.ReactElement {
|
|
131
160
|
const running = skills.filter((s) => s.status === 'running');
|
|
132
161
|
const pending = skills.filter((s) => s.status === 'pending');
|
|
133
162
|
|
|
134
|
-
// Build static items: header first, then completed skills
|
|
135
|
-
const staticItems: StaticItem[] = [
|
|
136
|
-
{ type: 'header' },
|
|
137
|
-
...completedItems.map((skill) => ({ type: 'skill' as const, skill })),
|
|
138
|
-
];
|
|
139
|
-
|
|
140
163
|
return (
|
|
141
|
-
|
|
142
|
-
{/*
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
SKILLS
|
|
150
|
-
</Text>
|
|
151
|
-
);
|
|
152
|
-
case 'skill':
|
|
153
|
-
return <CompletedSkill key={item.skill.name} skill={item.skill} />;
|
|
154
|
-
}
|
|
155
|
-
}}
|
|
164
|
+
<Box flexDirection="column">
|
|
165
|
+
{/*
|
|
166
|
+
* Completed skills - passed directly to Static WITHOUT wrapper objects.
|
|
167
|
+
* completedItems elements have stable references (same objects from parent),
|
|
168
|
+
* so Ink can correctly track which items are new vs already rendered.
|
|
169
|
+
*/}
|
|
170
|
+
<Static items={completedItems}>
|
|
171
|
+
{(skill) => <CompletedSkill key={skill.name} skill={skill} />}
|
|
156
172
|
</Static>
|
|
157
173
|
|
|
158
|
-
{/* Dynamic content
|
|
159
|
-
|
|
160
|
-
{
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
{
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
</Box>
|
|
169
|
-
</>
|
|
174
|
+
{/* Dynamic content - updates in place */}
|
|
175
|
+
{running.map((skill) => (
|
|
176
|
+
<RunningSkill key={skill.name} skill={skill} />
|
|
177
|
+
))}
|
|
178
|
+
{pending.map((skill) => (
|
|
179
|
+
<Text key={skill.name} dimColor>
|
|
180
|
+
{ICON_PENDING} {skill.displayName}
|
|
181
|
+
</Text>
|
|
182
|
+
))}
|
|
183
|
+
</Box>
|
|
170
184
|
);
|
|
171
185
|
}
|
|
172
186
|
|
|
@@ -206,14 +220,28 @@ export async function runSkillTasksWithInk(
|
|
|
206
220
|
const completedItems: SkillState[] = [];
|
|
207
221
|
const completedNames = new Set<string>();
|
|
208
222
|
|
|
223
|
+
// Print header before Ink starts - this avoids multiple Static components
|
|
224
|
+
// which can cause layout conflicts due to absolute positioning
|
|
225
|
+
process.stderr.write('\x1b[1mSKILLS\x1b[0m\n');
|
|
226
|
+
|
|
209
227
|
// Create Ink instance
|
|
210
228
|
const { rerender, unmount } = render(
|
|
211
229
|
<SkillRunner skills={skillStates} completedItems={completedItems} />,
|
|
212
230
|
{ stdout: process.stderr }
|
|
213
231
|
);
|
|
214
232
|
|
|
233
|
+
// Batch UI updates to prevent rapid consecutive rerenders that cause duplicate lines.
|
|
234
|
+
// Without batching, multiple callbacks firing in quick succession (e.g., 5 files
|
|
235
|
+
// starting simultaneously) trigger 5 immediate rerenders, which Ink cannot
|
|
236
|
+
// process correctly, resulting in the same line appearing multiple times.
|
|
237
|
+
let updatePending = false;
|
|
215
238
|
const updateUI = () => {
|
|
216
|
-
|
|
239
|
+
if (updatePending) return;
|
|
240
|
+
updatePending = true;
|
|
241
|
+
setImmediate(() => {
|
|
242
|
+
updatePending = false;
|
|
243
|
+
rerender(<SkillRunner skills={[...skillStates]} completedItems={[...completedItems]} />);
|
|
244
|
+
});
|
|
217
245
|
};
|
|
218
246
|
|
|
219
247
|
// Callbacks to update state
|
|
@@ -297,13 +325,14 @@ export async function runSkillTasksWithInk(
|
|
|
297
325
|
|
|
298
326
|
updateUI();
|
|
299
327
|
},
|
|
300
|
-
//
|
|
328
|
+
// CAUTION: Direct stderr writes while Ink is running can cause display glitches.
|
|
329
|
+
// These callbacks are rare (large prompts, debug mode) so the tradeoff is acceptable.
|
|
330
|
+
// If these cause issues, consider queueing messages and printing after unmount().
|
|
301
331
|
onLargePrompt: (_skillName, filename, lineRange, chars, estimatedTokens) => {
|
|
302
332
|
const location = `${filename}:${lineRange}`;
|
|
303
333
|
const size = `${Math.round(chars / 1000)}k chars (~${Math.round(estimatedTokens / 1000)}k tokens)`;
|
|
304
334
|
process.stderr.write(`\x1b[33m${figures.warning}\x1b[0m Large prompt for ${location}: ${size}\n`);
|
|
305
335
|
},
|
|
306
|
-
// Debug mode: show prompt sizes
|
|
307
336
|
onPromptSize: verbosity >= Verbosity.Debug
|
|
308
337
|
? (_skillName, filename, lineRange, systemChars, userChars, totalChars, estimatedTokens) => {
|
|
309
338
|
const location = `${filename}:${lineRange}`;
|