Compare commits
9
Commits
023d1610ba
...
c2bf5888d0
| 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"
|
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
|
if [ "$summary" = true ]; then
|
||||||
printf '%s\n' "$session_output" | sed '/^PASS session configuration$/d'
|
printf '%s\n' "$session_output" | sed '/^PASS session configuration$/d'
|
||||||
else
|
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" } }
|
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')
|
Check-Version 'PowerShell' $PSVersionTable.PSVersion.ToString() ([version]'5.1')
|
||||||
Require-Command jq; Require-Command python
|
Require-Command jq
|
||||||
if (Get-Command python -ErrorAction SilentlyContinue) {
|
$pythonVersion = $null
|
||||||
$pythonVersion = (& python --version 2>$null | Select-Object -First 1) -replace '^Python\s+', ''
|
foreach ($python in @('python', 'python3')) {
|
||||||
if ($LASTEXITCODE -eq 0) { Check-Version 'Python' $pythonVersion ([version]'3.11') } else { Fail 'Python 3.11 or newer is required' }
|
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 }
|
if ($failed) { Write-Error 'Capability check: FAIL'; exit 1 }
|
||||||
Write-Output 'Capability check: PASS'
|
Write-Output 'Capability check: PASS'
|
||||||
@@ -229,9 +229,35 @@ class Manager:
|
|||||||
self.command(arguments)
|
self.command(arguments)
|
||||||
self.cache[client].pop(selector, None)
|
self.cache[client].pop(selector, None)
|
||||||
elif record['kind'] == 'skill':
|
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'])
|
directory = safe_path(self.home, record['directory'])
|
||||||
if directory.exists():
|
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:
|
else:
|
||||||
package = record['package']
|
package = record['package']
|
||||||
self.command(['npm', 'uninstall', '--global', package])
|
self.command(['npm', 'uninstall', '--global', package])
|
||||||
|
|||||||
@@ -154,6 +154,8 @@ class InstallOptionsTests(unittest.TestCase):
|
|||||||
with self.subTest(shell=kind), tempfile.TemporaryDirectory() as directory:
|
with self.subTest(shell=kind), tempfile.TemporaryDirectory() as directory:
|
||||||
root = Path(directory) / 'repo'
|
root = Path(directory) / 'repo'
|
||||||
scripts = root / 'scripts'
|
scripts = root / 'scripts'
|
||||||
|
commands = scripts / 'commands'
|
||||||
|
commands.mkdir(parents=True)
|
||||||
shutil.copytree(ROOT / 'scripts/lib', scripts / 'lib', ignore=shutil.ignore_patterns('__pycache__'))
|
shutil.copytree(ROOT / 'scripts/lib', scripts / 'lib', ignore=shutil.ignore_patterns('__pycache__'))
|
||||||
home = Path(directory) / 'home'
|
home = Path(directory) / 'home'
|
||||||
home.mkdir()
|
home.mkdir()
|
||||||
@@ -168,10 +170,10 @@ class InstallOptionsTests(unittest.TestCase):
|
|||||||
(package / ('config.toml' if client == 'codex' else 'settings.json')).write_text(config)
|
(package / ('config.toml' if client == 'codex' else 'settings.json')).write_text(config)
|
||||||
suffix = 'ps1' if kind == 'powershell' else 'sh'
|
suffix = 'ps1' if kind == 'powershell' else 'sh'
|
||||||
for name in ('install', 'update'):
|
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')
|
content = content.replace("[Environment]::GetFolderPath('UserProfile')", '$env:TEST_INSTALL_HOME')
|
||||||
(scripts / (name + '.' + suffix)).write_text(content)
|
(commands / (name + '.' + suffix)).write_text(content)
|
||||||
(scripts / ('build.' + suffix)).write_text('param([switch]$Summary)' if kind == 'powershell' else 'exit 0\n')
|
(commands / ('build.' + suffix)).write_text('param([switch]$Summary)' if kind == 'powershell' else 'exit 0\n')
|
||||||
if kind == 'powershell':
|
if kind == 'powershell':
|
||||||
(scripts / 'lib/plugins.ps1').write_text(
|
(scripts / 'lib/plugins.ps1').write_text(
|
||||||
'function Select-ConfiguredPlugins { @{Selected=@(); Deselected=@()} }\n'
|
'function Select-ConfiguredPlugins { @{Selected=@(); Deselected=@()} }\n'
|
||||||
@@ -185,7 +187,7 @@ class InstallOptionsTests(unittest.TestCase):
|
|||||||
'run_plugin_command() { printf "CLI-MOCK %s\\n" "$2"; }\n')
|
'run_plugin_command() { printf "CLI-MOCK %s\\n" "$2"; }\n')
|
||||||
environment = dict(os.environ, HOME=home.as_posix(), TEST_INSTALL_HOME=str(home))
|
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, '')]:
|
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']
|
command = ([executable, '-NoProfile', '-File', entry, '-Shell', 'Bash', '-Client', 'Both', '-Summary']
|
||||||
if kind == 'powershell' else [executable, entry, '--shell', 'bash', '--client', 'both', '--summary'])
|
if kind == 'powershell' else [executable, entry, '--shell', 'bash', '--client', 'both', '--summary'])
|
||||||
if quick:
|
if quick:
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import unittest
|
|||||||
from unittest.mock import patch
|
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)
|
extensions = importlib.util.module_from_spec(spec)
|
||||||
spec.loader.exec_module(extensions)
|
spec.loader.exec_module(extensions)
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from tempfile import TemporaryDirectory
|
|||||||
import unittest
|
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)
|
MODULE = importlib.util.module_from_spec(SPEC)
|
||||||
SPEC.loader.exec_module(MODULE)
|
SPEC.loader.exec_module(MODULE)
|
||||||
|
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ class SelectionTests(unittest.TestCase):
|
|||||||
original = self.path.read_bytes()
|
original = self.path.read_bytes()
|
||||||
source = (ROOT / 'scripts/commands/update.ps1').read_text(encoding='utf-8-sig')
|
source = (ROOT / 'scripts/commands/update.ps1').read_text(encoding='utf-8-sig')
|
||||||
source = source.replace("[Environment]::GetFolderPath('UserProfile')", '$env:TEST_SELECTION_HOME')
|
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:
|
encoding='utf-8', delete=False) as stream:
|
||||||
stream.write(source)
|
stream.write(source)
|
||||||
entry = Path(stream.name)
|
entry = Path(stream.name)
|
||||||
|
|||||||
@@ -78,9 +78,9 @@ class SessionStateHookTests(unittest.TestCase):
|
|||||||
base = Path(directory)
|
base = Path(directory)
|
||||||
repository = base / 'repository'
|
repository = base / 'repository'
|
||||||
shutil.copytree(ROOT / 'shared/hooks/scripts', repository / 'shared/hooks/scripts')
|
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'):
|
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 = base / 'workspace ü'
|
||||||
workspace.mkdir()
|
workspace.mkdir()
|
||||||
environment = dict(os.environ, TASK_WORKSPACE=str(workspace),
|
environment = dict(os.environ, TASK_WORKSPACE=str(workspace),
|
||||||
|
|||||||
@@ -13,12 +13,15 @@ ROOT = Path(__file__).resolve().parent.parent.parent
|
|||||||
class TelemetryTests(unittest.TestCase):
|
class TelemetryTests(unittest.TestCase):
|
||||||
def test_bash_record_disable_and_summary(self):
|
def test_bash_record_disable_and_summary(self):
|
||||||
bash = shutil.which('bash')
|
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:
|
if not bash:
|
||||||
self.skipTest('Bash unavailable')
|
self.skipTest('Bash unavailable')
|
||||||
with tempfile.TemporaryDirectory() as directory:
|
with tempfile.TemporaryDirectory() as directory:
|
||||||
root = Path(directory)
|
root = Path(directory)
|
||||||
script = root / 'scripts/commands/telemetry.sh'
|
script = root / 'scripts/commands/telemetry.sh'
|
||||||
script.parent.mkdir()
|
script.parent.mkdir(parents=True)
|
||||||
shutil.copy(ROOT / 'scripts/commands/telemetry.sh', script)
|
shutil.copy(ROOT / 'scripts/commands/telemetry.sh', script)
|
||||||
env = dict(os.environ, AI_CONFIG_TELEMETRY='1')
|
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)
|
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