Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2bf5888d0 | ||
|
|
43e1487bb3 | ||
|
|
b6f111977d | ||
|
|
efec24a4eb | ||
|
|
797e53ff3e | ||
|
|
28a8bd70eb | ||
|
|
dffc956f27 | ||
|
|
72338270d0 | ||
|
|
25a9579eee |
No files matched your search
@@ -85,7 +85,7 @@ quote_toml() {
|
||||
printf '"%s"' "$value"
|
||||
}
|
||||
|
||||
session_output=$(bash "$shared/hooks/scripts/tests/test-session-config.sh" "$root") || { printf '%s\n' "$session_output" >&2; exit 1; }
|
||||
session_output=$(bash "$shared/hooks/scripts/test-session-config.sh" "$root") || { printf '%s\n' "$session_output" >&2; exit 1; }
|
||||
if [ "$summary" = true ]; then
|
||||
printf '%s\n' "$session_output" | sed '/^PASS session configuration$/d'
|
||||
else
|
||||
|
||||
@@ -9,11 +9,14 @@ function Version-AtLeast([string]$version, [version]$minimum) { try { return ([v
|
||||
function Check-Version([string]$name, [string]$version, [version]$minimum) { if (Version-AtLeast $version $minimum) { Pass "$name $version (minimum $minimum)" } else { Fail "$name $version is below minimum $minimum" } }
|
||||
|
||||
Check-Version 'PowerShell' $PSVersionTable.PSVersion.ToString() ([version]'5.1')
|
||||
Require-Command jq; Require-Command python
|
||||
if (Get-Command python -ErrorAction SilentlyContinue) {
|
||||
$pythonVersion = (& python --version 2>$null | Select-Object -First 1) -replace '^Python\s+', ''
|
||||
if ($LASTEXITCODE -eq 0) { Check-Version 'Python' $pythonVersion ([version]'3.11') } else { Fail 'Python 3.11 or newer is required' }
|
||||
Require-Command jq
|
||||
$pythonVersion = $null
|
||||
foreach ($python in @('python', 'python3')) {
|
||||
if (-not (Get-Command $python -ErrorAction SilentlyContinue)) { continue }
|
||||
$candidate = (& $python --version 2>$null | Select-Object -First 1) -replace '^Python\s+', ''
|
||||
if ($LASTEXITCODE -eq 0) { $pythonVersion = $candidate; break }
|
||||
}
|
||||
if ($null -ne $pythonVersion) { Check-Version 'Python' $pythonVersion ([version]'3.11') } else { Fail 'Python 3.11 or newer is required' }
|
||||
|
||||
if ($failed) { Write-Error 'Capability check: FAIL'; exit 1 }
|
||||
Write-Output 'Capability check: PASS'
|
||||
@@ -229,9 +229,35 @@ class Manager:
|
||||
self.command(arguments)
|
||||
self.cache[client].pop(selector, None)
|
||||
elif record['kind'] == 'skill':
|
||||
empty_candidates = set()
|
||||
for relative, expected in list(record['files'].items()):
|
||||
path = safe_path(self.home, relative)
|
||||
if path.exists():
|
||||
if not path.is_file() or digest(path) != expected:
|
||||
print(f'WARN Preserving modified skill file: {relative}')
|
||||
continue
|
||||
path.unlink()
|
||||
parent = path.parent
|
||||
directory = safe_path(self.home, record['directory'])
|
||||
while parent != directory.parent:
|
||||
empty_candidates.add(parent)
|
||||
parent = parent.parent
|
||||
del record['files'][relative]
|
||||
self.save()
|
||||
directory = safe_path(self.home, record['directory'])
|
||||
if directory.exists():
|
||||
shutil.rmtree(directory)
|
||||
for path in sorted(empty_candidates, key=lambda p: len(p.parts), reverse=True):
|
||||
if path.is_dir() and not path.is_symlink():
|
||||
try:
|
||||
path.rmdir()
|
||||
except OSError:
|
||||
pass
|
||||
try:
|
||||
directory.rmdir()
|
||||
except OSError:
|
||||
pass
|
||||
if record['files']:
|
||||
return
|
||||
else:
|
||||
package = record['package']
|
||||
self.command(['npm', 'uninstall', '--global', package])
|
||||
|
||||
@@ -154,6 +154,8 @@ class InstallOptionsTests(unittest.TestCase):
|
||||
with self.subTest(shell=kind), tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory) / 'repo'
|
||||
scripts = root / 'scripts'
|
||||
commands = scripts / 'commands'
|
||||
commands.mkdir(parents=True)
|
||||
shutil.copytree(ROOT / 'scripts/lib', scripts / 'lib', ignore=shutil.ignore_patterns('__pycache__'))
|
||||
home = Path(directory) / 'home'
|
||||
home.mkdir()
|
||||
@@ -168,10 +170,10 @@ class InstallOptionsTests(unittest.TestCase):
|
||||
(package / ('config.toml' if client == 'codex' else 'settings.json')).write_text(config)
|
||||
suffix = 'ps1' if kind == 'powershell' else 'sh'
|
||||
for name in ('install', 'update'):
|
||||
content = (ROOT / 'scripts' / (name + '.' + suffix)).read_text(encoding='utf-8-sig')
|
||||
content = (ROOT / 'scripts/commands' / (name + '.' + suffix)).read_text(encoding='utf-8-sig')
|
||||
content = content.replace("[Environment]::GetFolderPath('UserProfile')", '$env:TEST_INSTALL_HOME')
|
||||
(scripts / (name + '.' + suffix)).write_text(content)
|
||||
(scripts / ('build.' + suffix)).write_text('param([switch]$Summary)' if kind == 'powershell' else 'exit 0\n')
|
||||
(commands / (name + '.' + suffix)).write_text(content)
|
||||
(commands / ('build.' + suffix)).write_text('param([switch]$Summary)' if kind == 'powershell' else 'exit 0\n')
|
||||
if kind == 'powershell':
|
||||
(scripts / 'lib/plugins.ps1').write_text(
|
||||
'function Select-ConfiguredPlugins { @{Selected=@(); Deselected=@()} }\n'
|
||||
@@ -185,7 +187,7 @@ class InstallOptionsTests(unittest.TestCase):
|
||||
'run_plugin_command() { printf "CLI-MOCK %s\\n" "$2"; }\n')
|
||||
environment = dict(os.environ, HOME=home.as_posix(), TEST_INSTALL_HOME=str(home))
|
||||
for name, quick, answers in [('install', False, 'y\nn\nn\nn\n'), ('update', True, '')]:
|
||||
entry = str(scripts / (name + '.' + suffix))
|
||||
entry = str(commands / (name + '.' + suffix))
|
||||
command = ([executable, '-NoProfile', '-File', entry, '-Shell', 'Bash', '-Client', 'Both', '-Summary']
|
||||
if kind == 'powershell' else [executable, entry, '--shell', 'bash', '--client', 'both', '--summary'])
|
||||
if quick:
|
||||
|
||||
@@ -9,7 +9,7 @@ import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
spec = importlib.util.spec_from_file_location('extensions', Path(__file__).parent / 'lib' / 'managed-extensions.py')
|
||||
spec = importlib.util.spec_from_file_location('extensions', Path(__file__).parents[2] / 'scripts/lib/managed-extensions.py')
|
||||
extensions = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(extensions)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ from tempfile import TemporaryDirectory
|
||||
import unittest
|
||||
|
||||
|
||||
SPEC = importlib.util.spec_from_file_location('prompt_inventory', Path(__file__).parent / 'lib/prompt-inventory.py')
|
||||
SPEC = importlib.util.spec_from_file_location('prompt_inventory', Path(__file__).parents[2] / 'scripts/lib/prompt-inventory.py')
|
||||
MODULE = importlib.util.module_from_spec(SPEC)
|
||||
SPEC.loader.exec_module(MODULE)
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ class SelectionTests(unittest.TestCase):
|
||||
original = self.path.read_bytes()
|
||||
source = (ROOT / 'scripts/commands/update.ps1').read_text(encoding='utf-8-sig')
|
||||
source = source.replace("[Environment]::GetFolderPath('UserProfile')", '$env:TEST_SELECTION_HOME')
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.tmp.ps1', dir=ROOT / 'scripts',
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.tmp.ps1', dir=ROOT / 'scripts/commands',
|
||||
encoding='utf-8', delete=False) as stream:
|
||||
stream.write(source)
|
||||
entry = Path(stream.name)
|
||||
|
||||
@@ -78,9 +78,9 @@ class SessionStateHookTests(unittest.TestCase):
|
||||
base = Path(directory)
|
||||
repository = base / 'repository'
|
||||
shutil.copytree(ROOT / 'shared/hooks/scripts', repository / 'shared/hooks/scripts')
|
||||
(repository / 'scripts').mkdir()
|
||||
(repository / 'scripts/commands').mkdir(parents=True)
|
||||
for filename in ('session-state.ps1', 'session-state.sh'):
|
||||
shutil.copy(ROOT / 'scripts' / filename, repository / 'scripts' / filename)
|
||||
shutil.copy(ROOT / 'scripts/commands' / filename, repository / 'scripts/commands' / filename)
|
||||
workspace = base / 'workspace ü'
|
||||
workspace.mkdir()
|
||||
environment = dict(os.environ, TASK_WORKSPACE=str(workspace),
|
||||
|
||||
@@ -13,12 +13,15 @@ ROOT = Path(__file__).resolve().parent.parent.parent
|
||||
class TelemetryTests(unittest.TestCase):
|
||||
def test_bash_record_disable_and_summary(self):
|
||||
bash = shutil.which('bash')
|
||||
if os.name == 'nt':
|
||||
candidate = Path(os.environ.get('ProgramFiles', 'C:/Program Files')) / 'Git/bin/bash.exe'
|
||||
bash = str(candidate) if candidate.exists() else None
|
||||
if not bash:
|
||||
self.skipTest('Bash unavailable')
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
script = root / 'scripts/commands/telemetry.sh'
|
||||
script.parent.mkdir()
|
||||
script.parent.mkdir(parents=True)
|
||||
shutil.copy(ROOT / 'scripts/commands/telemetry.sh', script)
|
||||
env = dict(os.environ, AI_CONFIG_TELEMETRY='1')
|
||||
result = subprocess.run([bash, str(script), 'record', 'subagent-stop', '--role', 'reviewer', '--filesRead', '3', '--outcome', 'findings'], env=env, capture_output=True, text=True)
|
||||
|
||||
Reference in new issue
Block a user