svharness 0.15.11 → 0.15.13
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 +106 -2
- package/auto/auto-harness-detail-design.md +136 -4
- package/auto/skills/svharness/SKILL.md +44 -1
- package/auto/templates/auto-pack-req.config.example.yaml +29 -0
- package/auto/templates/auto.config.example.yaml +1 -1
- package/auto/templates/phase-prompts/S40-adversarial-review.md +31 -0
- package/auto/templates/phase-prompts/S40-review.md +22 -0
- package/auto/templates/phase-prompts/S40-sample-trace.md +26 -0
- package/auto/templates/requirements-review-rubric.yaml +79 -0
- package/dist/commands/auto-pack-req.js +70 -0
- package/dist/commands/auto.js +16 -1
- package/dist/commands/convert.js +2 -0
- package/dist/commands/shell-integration.js +29 -56
- package/dist/config/merge-options.js +2 -0
- package/dist/config/normalize.js +7 -0
- package/dist/constants/convert.js +5 -0
- package/dist/core/markitdown-client.js +7 -2
- package/dist/index.js +77 -5
- package/dist/lib/acp-agent-cli-resolver.js +193 -0
- package/dist/lib/acp-client.js +4 -2
- package/dist/lib/agent-launcher.js +9 -4
- package/dist/lib/auto-assets.js +1 -0
- package/dist/lib/auto-optimize.js +23 -3
- package/dist/lib/auto-orchestrator.js +53 -20
- package/dist/lib/auto-pack-req-context.js +88 -0
- package/dist/lib/auto-pack-req-finalize.js +28 -0
- package/dist/lib/auto-req-pack-review.js +161 -0
- package/dist/lib/auto-sample-trace.js +144 -0
- package/dist/lib/auto-state.js +124 -15
- package/dist/lib/gate-checker.js +20 -10
- package/dist/lib/phase-runner.js +13 -2
- package/dist/lib/ps-codechat-alias.js +29 -16
- package/dist/lib/review-parser.js +14 -0
- package/dist/lib/score-aggregator.js +21 -0
- package/dist/lib/win-registry.js +1 -1
- package/dist/utils/validate-args.js +2 -1
- package/package.json +3 -2
- package/templates/codechat/Start-CodeChat.ps1 +176 -135
- package/templates/codechat/bash.exe.stackdump +29 -0
- package/templates/codechat/docs/project-structure.md +59 -0
- package/templates/svharness.config.example.yaml +2 -0
- package/dist/lib/launch-script-path.js +0 -24
- package/templates/codechat/.claude/.env +0 -59
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
# UTF-8 BOM
|
|
3
|
-
# Compatible with both
|
|
1
|
+
# Standalone CodeChat launcher.
|
|
2
|
+
# UTF-8 BOM is added by Install-CodeChatContextMenu for PS 5.1 -File mode.
|
|
3
|
+
# Compatible with both irm|iex and -File invocation.
|
|
4
4
|
# Suppress Set-ExecutionPolicy errors when Group Policy overrides (common on enterprise machines).
|
|
5
5
|
try { Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force -ErrorAction Stop | Out-Null } catch {}
|
|
6
6
|
# Ensure console output uses UTF-8 so Chinese labels print correctly
|
|
7
7
|
try { chcp 65001 | Out-Null } catch {}
|
|
8
8
|
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
|
|
9
9
|
$OutputEncoding = [System.Text.UTF8Encoding]::new($false)
|
|
10
|
-
$Action='Install'; $WorkDir=(Get-Location).Path; $
|
|
10
|
+
$Action='Install'; $WorkDir=(Get-Location).Path; $NoSkipPermissions=$false; $ExtraArgs=@()
|
|
11
11
|
for($__i=0;$__i -lt $args.Count;$__i++){
|
|
12
12
|
switch -Regex ($args[$__i]){
|
|
13
13
|
'^-Action$' { $Action=$args[++$__i] }
|
|
14
14
|
'^-WorkDir$' { $WorkDir=$args[++$__i] }
|
|
15
|
-
'^-NoSyncEnv$' { $NoSyncEnv=$true }
|
|
16
15
|
'^-NoSkipPermissions$' { $NoSkipPermissions=$true }
|
|
17
16
|
default { $ExtraArgs += $args[$__i] }
|
|
18
17
|
}
|
|
@@ -21,14 +20,12 @@ Remove-Variable __i
|
|
|
21
20
|
|
|
22
21
|
# The URL this script was downloaded from (used when re-downloading in iex mode)
|
|
23
22
|
$script:DownloadUrl = 'https://v-hub.desaysz.site/Start-CodeChat.ps1'
|
|
23
|
+
$script:IconDownloadUrl = 'https://v-hub.desaysz.site/codechat-agent.ico'
|
|
24
24
|
|
|
25
25
|
$ErrorActionPreference = 'Stop'
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
} else {
|
|
30
|
-
'Launch CodeChat CLI here'
|
|
31
|
-
}
|
|
27
|
+
# ASCII-only label avoids mojibake in Explorer context menu (registry encoding).
|
|
28
|
+
$script:MenuLabel = 'Launch CodeChat CLI here'
|
|
32
29
|
$script:MenuKeyBg = 'HKCU:\Software\Classes\Directory\Background\shell\CodeChatStandaloneAgent'
|
|
33
30
|
$script:MenuKeyDir = 'HKCU:\Software\Classes\Directory\shell\CodeChatStandaloneAgent'
|
|
34
31
|
$script:SvharnessMenuKeyBg = 'HKCU:\Software\Classes\Directory\Background\shell\SvharnessLaunchCodeChatAgent'
|
|
@@ -176,127 +173,138 @@ function Find-CodeChatRunner {
|
|
|
176
173
|
}
|
|
177
174
|
}
|
|
178
175
|
|
|
179
|
-
function
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
$
|
|
191
|
-
|
|
192
|
-
$
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
$val = $val.Substring(1, $val.Length - 2)
|
|
197
|
-
$wasQuoted = $true
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
# Strip inline comment (# outside quotes only)
|
|
201
|
-
if (-not $wasQuoted) {
|
|
202
|
-
$hashIdx = $val.IndexOf('#')
|
|
203
|
-
if ($hashIdx -ge 0) {
|
|
204
|
-
$val = $val.Substring(0, $hashIdx).TrimEnd()
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
$result[$key] = $val
|
|
176
|
+
function Initialize-ConsoleUtf8 {
|
|
177
|
+
try { chcp 65001 | Out-Null } catch {}
|
|
178
|
+
[Console]::InputEncoding = [System.Text.UTF8Encoding]::new($false)
|
|
179
|
+
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
|
|
180
|
+
$script:OutputEncoding = [System.Text.UTF8Encoding]::new($false)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function Get-ExtraArgsFromJsonFragment {
|
|
184
|
+
param([string]$Fragment)
|
|
185
|
+
if ([string]::IsNullOrWhiteSpace($Fragment)) { return @() }
|
|
186
|
+
if ($Fragment -match '^\[\s*(.*)\s*\]$') {
|
|
187
|
+
$inner = $Matches[1]
|
|
188
|
+
if ([string]::IsNullOrWhiteSpace($inner)) { return @() }
|
|
189
|
+
return @([regex]::Matches($inner, '"((?:\\.|[^"\\])*)"') | ForEach-Object { $_.Groups[1].Value })
|
|
190
|
+
}
|
|
191
|
+
if ($Fragment -match '^"\s*([^"]*)\s*"$') {
|
|
192
|
+
return @($Matches[1].Trim() -split '\s+' | Where-Object { $_ })
|
|
208
193
|
}
|
|
209
|
-
return
|
|
194
|
+
return @()
|
|
210
195
|
}
|
|
211
196
|
|
|
212
|
-
function
|
|
197
|
+
function Format-ExtraArgsJsonArray {
|
|
198
|
+
param([string[]]$ArgValues)
|
|
199
|
+
if (-not $ArgValues -or $ArgValues.Count -eq 0) { return '[]' }
|
|
200
|
+
$escaped = ($ArgValues | ForEach-Object {
|
|
201
|
+
'"{0}"' -f ([string]$_ -replace '\\', '\\' -replace '"', '\"')
|
|
202
|
+
}) -join ', '
|
|
203
|
+
return "[$escaped]"
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function Update-SectionExtraArgsInConfigJson {
|
|
213
207
|
param(
|
|
214
|
-
[string]$
|
|
215
|
-
[
|
|
208
|
+
[string]$JsonText,
|
|
209
|
+
[string]$SectionName,
|
|
210
|
+
[string[]]$RemoveArgs = @('-c'),
|
|
211
|
+
[string[]]$EnsureArgs = @('--dangerously-skip-permissions'),
|
|
212
|
+
[switch]$SkipEnsure
|
|
216
213
|
)
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
$
|
|
214
|
+
if ([string]::IsNullOrWhiteSpace($JsonText)) { return $JsonText }
|
|
215
|
+
|
|
216
|
+
$pattern = "(`"$SectionName`"\s*:\s*\{[\s\S]*?`"extra_args`"\s*:\s*)(\[[^\]]*\]|`"[^`"]*`"|\{\s*\})"
|
|
217
|
+
$match = [regex]::Match($JsonText, $pattern)
|
|
218
|
+
if (-not $match.Success) { return $JsonText }
|
|
219
|
+
|
|
220
|
+
$current = Get-ExtraArgsFromJsonFragment -Fragment $match.Groups[2].Value
|
|
221
|
+
$next = @($current | Where-Object { $_ -and ($_ -notin $RemoveArgs) })
|
|
222
|
+
if ($SkipEnsure) {
|
|
223
|
+
$next = @($next | Where-Object { $_ -notin $EnsureArgs })
|
|
224
|
+
} else {
|
|
225
|
+
foreach ($arg in $EnsureArgs) {
|
|
226
|
+
if ($arg -and ($arg -notin $next)) { $next += $arg }
|
|
230
227
|
}
|
|
231
228
|
}
|
|
232
|
-
|
|
233
|
-
$
|
|
234
|
-
|
|
235
|
-
$
|
|
236
|
-
|
|
229
|
+
|
|
230
|
+
$newFragment = Format-ExtraArgsJsonArray -ArgValues $next
|
|
231
|
+
$currentFragment = $match.Groups[2].Value
|
|
232
|
+
$isArrayFragment = $currentFragment -match '^\[\s*'
|
|
233
|
+
if ($isArrayFragment -and ($currentFragment -eq $newFragment)) { return $JsonText }
|
|
234
|
+
|
|
235
|
+
$headLen = $match.Groups[1].Index + $match.Groups[1].Length
|
|
236
|
+
$tailStart = $match.Groups[2].Index + $match.Groups[2].Length
|
|
237
|
+
return $JsonText.Substring(0, $headLen) + $newFragment + $JsonText.Substring($tailStart)
|
|
237
238
|
}
|
|
238
239
|
|
|
239
|
-
function
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
)
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
# Backward compat: also sync .env file for --env-file argument
|
|
257
|
-
$resolvedProject = (Resolve-Path -LiteralPath $projectEnv).Path
|
|
258
|
-
$resolvedUser = if (Test-Path -LiteralPath $userClaudeEnv) { (Resolve-Path -LiteralPath $userClaudeEnv).Path } else { $null }
|
|
259
|
-
if ($resolvedProject -ne $resolvedUser) {
|
|
260
|
-
$userDir = Split-Path -Parent $userClaudeEnv
|
|
261
|
-
if (-not (Test-Path -LiteralPath $userDir)) {
|
|
262
|
-
New-Item -ItemType Directory -Force -Path $userDir | Out-Null
|
|
240
|
+
function Repair-CodeChatBootstrapConfigLib {
|
|
241
|
+
# bootstrap Config.ps1 unwraps single-element JSON arrays to strings on load, and
|
|
242
|
+
# ConvertTo-Json may write extra_args as strings — patch once in the local CLI install.
|
|
243
|
+
$configPs1 = Join-Path $env:USERPROFILE '.codechat\cli_app\win\lib\Config.ps1'
|
|
244
|
+
if (-not (Test-Path -LiteralPath $configPs1)) { return }
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
$content = Get-Content -LiteralPath $configPs1 -Raw -Encoding UTF8
|
|
248
|
+
if (-not $content) { return }
|
|
249
|
+
|
|
250
|
+
$marker = 'Start-CodeChat: preserve single-element arrays'
|
|
251
|
+
if ($content -notmatch [regex]::Escape($marker)) {
|
|
252
|
+
$needle = " return `$list"
|
|
253
|
+
$replacement = " return ,@(`$list) # $marker"
|
|
254
|
+
if ($content.Contains($needle)) {
|
|
255
|
+
$content = $content.Replace($needle, $replacement)
|
|
256
|
+
Write-Utf8NoBom -Path $configPs1 -Value $content
|
|
263
257
|
}
|
|
264
|
-
Copy-Item -LiteralPath $projectEnv -Destination $userClaudeEnv -Force
|
|
265
258
|
}
|
|
266
|
-
|
|
259
|
+
} catch {
|
|
260
|
+
# Never block startup for bootstrap patch
|
|
267
261
|
}
|
|
262
|
+
}
|
|
268
263
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
264
|
+
function Ensure-BootstrapExtraArgs {
|
|
265
|
+
# Surgical edit only: strip legacy "-c" from extra_args; keep all other config fields/args.
|
|
266
|
+
param(
|
|
267
|
+
[switch]$SkipPermissions
|
|
268
|
+
)
|
|
272
269
|
|
|
273
|
-
|
|
274
|
-
if (Test-Path -LiteralPath $userCodechatEnv) {
|
|
275
|
-
return $userCodechatEnv
|
|
276
|
-
}
|
|
270
|
+
Repair-CodeChatBootstrapConfigLib
|
|
277
271
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
}
|
|
272
|
+
$configPath = Join-Path $env:USERPROFILE '.codechat\bootstrap\config.json'
|
|
273
|
+
$ensureArgs = @('--dangerously-skip-permissions')
|
|
281
274
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
275
|
+
if (-not (Test-Path -LiteralPath $configPath)) { return }
|
|
276
|
+
|
|
277
|
+
try {
|
|
278
|
+
$raw = Get-Content -LiteralPath $configPath -Raw -Encoding UTF8
|
|
279
|
+
if (-not $raw) { return }
|
|
280
|
+
|
|
281
|
+
$updated = $raw
|
|
282
|
+
foreach ($sectionName in @('claudecode', 'codechat')) {
|
|
283
|
+
$updated = Update-SectionExtraArgsInConfigJson `
|
|
284
|
+
-JsonText $updated `
|
|
285
|
+
-SectionName $sectionName `
|
|
286
|
+
-RemoveArgs @('-c') `
|
|
287
|
+
-EnsureArgs $ensureArgs `
|
|
288
|
+
-SkipEnsure:$SkipPermissions
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if ($updated -ne $raw) {
|
|
292
|
+
Write-Utf8NoBom -Path $configPath -Value $updated
|
|
293
|
+
}
|
|
294
|
+
} catch {
|
|
295
|
+
# Silently ignore — never block startup for config tweaks
|
|
296
|
+
}
|
|
287
297
|
}
|
|
288
298
|
|
|
289
299
|
function Invoke-CodeChatStart {
|
|
290
300
|
param(
|
|
291
301
|
[string]$TargetWorkDir,
|
|
292
|
-
[switch]$SkipEnvSync,
|
|
293
302
|
[switch]$SkipPermissions
|
|
294
303
|
)
|
|
295
304
|
|
|
296
305
|
Initialize-ConsoleUtf8
|
|
297
306
|
|
|
298
307
|
$resolvedWorkDir = (Resolve-Path -LiteralPath $TargetWorkDir).Path
|
|
299
|
-
$envFile = Sync-ProjectEnv -ProjectRoot $resolvedWorkDir -SkipSync:$SkipEnvSync
|
|
300
308
|
$resolved = Find-CodeChatRunner
|
|
301
309
|
|
|
302
310
|
$sourceLog = $resolved.Source
|
|
@@ -306,26 +314,25 @@ function Invoke-CodeChatStart {
|
|
|
306
314
|
|
|
307
315
|
Write-Host "CodeChat CLI: $($resolved.Runner) ($sourceLog)"
|
|
308
316
|
Write-Host "workdir: $resolvedWorkDir"
|
|
309
|
-
if ($envFile) {
|
|
310
|
-
Write-Host "env: $envFile"
|
|
311
|
-
}
|
|
312
317
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
$args += '--dangerously-skip-permissions'
|
|
321
|
-
}
|
|
322
|
-
# Append extra args forwarded from alias (e.g., -c for config path)
|
|
318
|
+
# Sync bootstrap extra_args for both codechat + claudecode before launch
|
|
319
|
+
Ensure-BootstrapExtraArgs -SkipPermissions:$SkipPermissions
|
|
320
|
+
|
|
321
|
+
# run.bat → bootstrap.ps1 only accepts -cwd <path> (two args).
|
|
322
|
+
# --cwd="path" is silently dropped when invoked via cmd.exe %*.
|
|
323
|
+
$args = @('-cwd', $resolvedWorkDir)
|
|
324
|
+
# Append extra args forwarded from alias
|
|
323
325
|
if ($ExtraArgs -and $ExtraArgs.Count -gt 0) {
|
|
324
326
|
$args += $ExtraArgs
|
|
325
327
|
}
|
|
326
328
|
|
|
327
329
|
& $resolved.Runner @args
|
|
328
|
-
|
|
330
|
+
$exitCode = $LASTEXITCODE
|
|
331
|
+
|
|
332
|
+
# bootstrap Update-CliPreference may rewrite extra_args; repair after CLI exits.
|
|
333
|
+
Ensure-BootstrapExtraArgs -SkipPermissions:$SkipPermissions
|
|
334
|
+
|
|
335
|
+
exit $exitCode
|
|
329
336
|
}
|
|
330
337
|
|
|
331
338
|
function Get-WtExecutable {
|
|
@@ -345,6 +352,9 @@ function Get-WtExecutable {
|
|
|
345
352
|
|
|
346
353
|
function Copy-OptionalIcon {
|
|
347
354
|
param([string]$SourceScriptPath)
|
|
355
|
+
if (Test-Path -LiteralPath $script:InstalledIcon) {
|
|
356
|
+
return $true
|
|
357
|
+
}
|
|
348
358
|
$candidates = @(
|
|
349
359
|
(Join-Path (Split-Path -Parent $SourceScriptPath) 'codechat-agent.ico'),
|
|
350
360
|
(Join-Path (Split-Path -Parent $SourceScriptPath) '..\assets\codechat-agent.ico'),
|
|
@@ -353,13 +363,41 @@ function Copy-OptionalIcon {
|
|
|
353
363
|
foreach ($icon in $candidates) {
|
|
354
364
|
try {
|
|
355
365
|
$resolved = Resolve-Path -LiteralPath $icon -ErrorAction Stop
|
|
356
|
-
Copy-Item -LiteralPath $resolved.Path -Destination $script:InstalledIcon -Force
|
|
366
|
+
Copy-Item -LiteralPath $resolved.Path -Destination $script:InstalledIcon -Force -ErrorAction Stop
|
|
357
367
|
return $true
|
|
358
368
|
} catch {}
|
|
359
369
|
}
|
|
360
370
|
return $false
|
|
361
371
|
}
|
|
362
372
|
|
|
373
|
+
function Download-MenuIcon {
|
|
374
|
+
if (Test-Path -LiteralPath $script:InstalledIcon) {
|
|
375
|
+
return $true
|
|
376
|
+
}
|
|
377
|
+
if (-not $script:IconDownloadUrl) {
|
|
378
|
+
return $false
|
|
379
|
+
}
|
|
380
|
+
try {
|
|
381
|
+
Invoke-WebRequest -Uri $script:IconDownloadUrl -OutFile $script:InstalledIcon -ErrorAction Stop
|
|
382
|
+
return (Test-Path -LiteralPath $script:InstalledIcon)
|
|
383
|
+
} catch {
|
|
384
|
+
try {
|
|
385
|
+
(New-Object System.Net.WebClient).DownloadFile($script:IconDownloadUrl, $script:InstalledIcon)
|
|
386
|
+
return (Test-Path -LiteralPath $script:InstalledIcon)
|
|
387
|
+
} catch {
|
|
388
|
+
return $false
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
function Ensure-MenuIcon {
|
|
394
|
+
param([string]$SourceScriptPath)
|
|
395
|
+
if (Copy-OptionalIcon -SourceScriptPath $SourceScriptPath) {
|
|
396
|
+
return $true
|
|
397
|
+
}
|
|
398
|
+
return (Download-MenuIcon)
|
|
399
|
+
}
|
|
400
|
+
|
|
363
401
|
function Register-ExplorerMenu {
|
|
364
402
|
param(
|
|
365
403
|
[string]$MenuKey,
|
|
@@ -369,7 +407,8 @@ function Register-ExplorerMenu {
|
|
|
369
407
|
New-Item -Path $MenuKey -Force | Out-Null
|
|
370
408
|
Set-ItemProperty -Path $MenuKey -Name '(default)' -Value $script:MenuLabel
|
|
371
409
|
if ($IconPath -and (Test-Path -LiteralPath $IconPath)) {
|
|
372
|
-
|
|
410
|
+
$iconValue = "$((Resolve-Path -LiteralPath $IconPath).Path),0"
|
|
411
|
+
Set-ItemProperty -Path $MenuKey -Name 'Icon' -Value $iconValue
|
|
373
412
|
}
|
|
374
413
|
New-Item -Path "$MenuKey\command" -Force | Out-Null
|
|
375
414
|
Set-ItemProperty -Path "$MenuKey\command" -Name '(default)' -Value $Command
|
|
@@ -415,7 +454,12 @@ function Install-CodeChatContextMenu {
|
|
|
415
454
|
$null = New-Item -ItemType Directory -Force -Path $script:StandaloneDir
|
|
416
455
|
Copy-Item -LiteralPath $sourceScript -Destination $script:InstalledScript -Force
|
|
417
456
|
}
|
|
418
|
-
|
|
457
|
+
# Re-add UTF-8 BOM for PS 5.1 -File mode (required for Chinese chars in menu labels)
|
|
458
|
+
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
|
459
|
+
$savedContent = Get-Content -LiteralPath $script:InstalledScript -Raw -Encoding UTF8
|
|
460
|
+
[System.IO.File]::WriteAllText($script:InstalledScript, $savedContent, $utf8Bom)
|
|
461
|
+
|
|
462
|
+
$hasIcon = Ensure-MenuIcon -SourceScriptPath $sourceScript
|
|
419
463
|
|
|
420
464
|
$psArgs = "-NoExit -NoProfile -ExecutionPolicy Bypass -File `"$($script:InstalledScript)`" -Action Start -WorkDir"
|
|
421
465
|
$wt = Get-WtExecutable
|
|
@@ -434,6 +478,11 @@ function Install-CodeChatContextMenu {
|
|
|
434
478
|
|
|
435
479
|
Write-Host "[ok] Context menu registered: $($script:MenuLabel)"
|
|
436
480
|
Write-Host "[info] script: $($script:InstalledScript)"
|
|
481
|
+
if ($hasIcon) {
|
|
482
|
+
Write-Host "[info] icon: $($script:InstalledIcon)"
|
|
483
|
+
} else {
|
|
484
|
+
Write-Host "[warn] icon not found; menu will have no icon"
|
|
485
|
+
}
|
|
437
486
|
if ($wt) {
|
|
438
487
|
Write-Host "[info] terminal: Windows Terminal"
|
|
439
488
|
}
|
|
@@ -513,16 +562,6 @@ function Install-CodeChatAlias {
|
|
|
513
562
|
Write-Utf8NoBom -Path $PROFILE -Value $joined
|
|
514
563
|
}
|
|
515
564
|
|
|
516
|
-
# First-run bootstrap: copy ~/.codechat/.env → <cwd>/.claude/.env
|
|
517
|
-
$claudeDir = Join-Path (Get-Location).Path '.claude'
|
|
518
|
-
$claudeEnv = Join-Path $claudeDir '.env'
|
|
519
|
-
$homeEnv = Join-Path $HOME '.codechat\.env'
|
|
520
|
-
if (-not (Test-Path $claudeEnv) -and (Test-Path $homeEnv)) {
|
|
521
|
-
if (-not (Test-Path $claudeDir)) { New-Item -ItemType Directory -Path $claudeDir -Force | Out-Null }
|
|
522
|
-
Copy-Item -Path $homeEnv -Destination $claudeEnv -Force
|
|
523
|
-
Write-Host "[info] copied $homeEnv -> $claudeEnv"
|
|
524
|
-
}
|
|
525
|
-
|
|
526
565
|
# Resolve the installed script path (this script after InstallMenu copies it)
|
|
527
566
|
$aliasTarget = if (Test-Path -LiteralPath $script:InstalledScript) { $script:InstalledScript } else { $PSCommandPath }
|
|
528
567
|
|
|
@@ -546,9 +585,6 @@ function codechat {
|
|
|
546
585
|
# Load into current session
|
|
547
586
|
try { . $PROFILE } catch {}
|
|
548
587
|
Write-Host "[ok] Alias 'codechat' installed to $PROFILE"
|
|
549
|
-
if (-not (Test-Path $claudeEnv) -and -not (Test-Path $homeEnv)) {
|
|
550
|
-
Write-Host "[warn] No .env found. Open this project in VS Code or Android Studio and run the CodeChat plugin first."
|
|
551
|
-
}
|
|
552
588
|
}
|
|
553
589
|
|
|
554
590
|
function Uninstall-CodeChatAlias {
|
|
@@ -565,7 +601,7 @@ function Uninstall-CodeChatAlias {
|
|
|
565
601
|
|
|
566
602
|
switch ($Action) {
|
|
567
603
|
'Start' {
|
|
568
|
-
Invoke-CodeChatStart -TargetWorkDir $WorkDir -
|
|
604
|
+
Invoke-CodeChatStart -TargetWorkDir $WorkDir -SkipPermissions:$NoSkipPermissions
|
|
569
605
|
}
|
|
570
606
|
'InstallMenu' {
|
|
571
607
|
Install-CodeChatContextMenu
|
|
@@ -585,5 +621,10 @@ switch ($Action) {
|
|
|
585
621
|
'Install' {
|
|
586
622
|
Install-CodeChatContextMenu
|
|
587
623
|
Install-CodeChatAlias
|
|
624
|
+
Ensure-BootstrapExtraArgs -SkipPermissions:$NoSkipPermissions
|
|
625
|
+
}
|
|
626
|
+
'Uninstall' {
|
|
627
|
+
Uninstall-CodeChatContextMenu
|
|
628
|
+
Uninstall-CodeChatAlias
|
|
588
629
|
}
|
|
589
630
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
Stack trace:
|
|
2
|
+
Frame Function Args
|
|
3
|
+
0007FFFFBF80 00021005FE8E (000210285F68, 00021026AB6E, 000000000000, 0007FFFFAE80) msys-2.0.dll+0x1FE8E
|
|
4
|
+
0007FFFFBF80 0002100467F9 (000000000000, 000000000000, 000000000000, 0007FFFFC258) msys-2.0.dll+0x67F9
|
|
5
|
+
0007FFFFBF80 000210046832 (000210286019, 0007FFFFBE38, 000000000000, 000000000000) msys-2.0.dll+0x6832
|
|
6
|
+
0007FFFFBF80 000210068CF6 (000000000000, 000000000000, 000000000000, 000000000000) msys-2.0.dll+0x28CF6
|
|
7
|
+
0007FFFFBF80 000210068E24 (0007FFFFBF90, 000000000000, 000000000000, 000000000000) msys-2.0.dll+0x28E24
|
|
8
|
+
0007FFFFC260 00021006A225 (0007FFFFBF90, 000000000000, 000000000000, 000000000000) msys-2.0.dll+0x2A225
|
|
9
|
+
End of stack trace
|
|
10
|
+
Loaded modules:
|
|
11
|
+
000100400000 bash.exe
|
|
12
|
+
7FF8D7220000 ntdll.dll
|
|
13
|
+
7FF8D5CA0000 KERNEL32.DLL
|
|
14
|
+
7FF8D4870000 KERNELBASE.dll
|
|
15
|
+
7FF8D5080000 USER32.dll
|
|
16
|
+
7FF8D4F30000 win32u.dll
|
|
17
|
+
000210040000 msys-2.0.dll
|
|
18
|
+
7FF8D6BC0000 GDI32.dll
|
|
19
|
+
7FF8D4E10000 gdi32full.dll
|
|
20
|
+
7FF8D4D70000 msvcp_win.dll
|
|
21
|
+
7FF8D4750000 ucrtbase.dll
|
|
22
|
+
7FF8D5E70000 advapi32.dll
|
|
23
|
+
7FF8D6070000 msvcrt.dll
|
|
24
|
+
7FF8D6DB0000 sechost.dll
|
|
25
|
+
7FF8D5050000 bcrypt.dll
|
|
26
|
+
7FF8D6980000 RPCRT4.dll
|
|
27
|
+
7FF8D3E60000 CRYPTBASE.DLL
|
|
28
|
+
7FF8D4FD0000 bcryptPrimitives.dll
|
|
29
|
+
7FF8D56F0000 IMM32.DLL
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# 前端目录(Vue3 + TypeScript + Pinia)
|
|
2
|
+
src/
|
|
3
|
+
├── api/ # API 接口定义层(只写 URL 和 method,每个业务模块一个文件)
|
|
4
|
+
├── mock/
|
|
5
|
+
│ ├── index.js # 路由映射表 (mockDataMap),所有 Mock 路由在此注册
|
|
6
|
+
│ ├── interceptor.js # axios 拦截器(Mock 核心开关)
|
|
7
|
+
│ └── modules/ # Mock 数据实现,与 api/ 一一对应
|
|
8
|
+
├── stores/ # Pinia 状态层(可选,用于跨组件共享数据,内部仍调用 api/)
|
|
9
|
+
├── views/ # 页面
|
|
10
|
+
├── components/ # 公共组件(图表、顶栏、面板等)
|
|
11
|
+
├── router/
|
|
12
|
+
│ └── index.ts # 路由配置(含权限守卫)
|
|
13
|
+
└── utils/
|
|
14
|
+
└── request.ts # axios 封装(含 Mock 拦截接入点)
|
|
15
|
+
|
|
16
|
+
# 后端目录(SpringBoot DDD 分层,包名以 [基础包名] 为前缀)
|
|
17
|
+
[基础包名]/
|
|
18
|
+
├── application/
|
|
19
|
+
│ ├── adapter/
|
|
20
|
+
│ │ ├── api/ # REST 入口(XxxAppService)
|
|
21
|
+
│ │ ├── consumer/ # MQ 消费者
|
|
22
|
+
│ │ └── scheduler/ # 定时任务(XxxTask)
|
|
23
|
+
│ ├── service/
|
|
24
|
+
│ │ ├── XxxAppService.java # 应用服务
|
|
25
|
+
│ │ └── process/
|
|
26
|
+
│ │ └── XxxProcess.java # 编排流程
|
|
27
|
+
│ ├── repository/ # 仓储接口(IXxxAppRepository)
|
|
28
|
+
│ ├── dto/ # 请求/响应体(XxxReqDTO / XxxRespDTO)
|
|
29
|
+
│ ├── converter/ # 转换器(XxxAppConverter)
|
|
30
|
+
│ ├── external/ # 外部服务接口(IXxxExternalService)
|
|
31
|
+
│ └── error/ # 错误码(AppErrorEnum)
|
|
32
|
+
├── domain/
|
|
33
|
+
│ └── [聚合根]/
|
|
34
|
+
│ ├── entity/ # 实体(无后缀)/ 值对象(XxxVO)
|
|
35
|
+
│ ├── event/ # 领域事件(完成时态,XxxEvent)
|
|
36
|
+
│ ├── repository/ # 仓储接口(IXxxRepository)
|
|
37
|
+
│ ├── constants/ # 常量(XxxConstants)
|
|
38
|
+
│ ├── enums/ # 枚举(XxxEnum)
|
|
39
|
+
│ ├── error/ # 错误码(XxxErrorEnum)
|
|
40
|
+
│ └── properties/
|
|
41
|
+
├── infrastructure/
|
|
42
|
+
│ └── [聚合根]/
|
|
43
|
+
│ └── repository/
|
|
44
|
+
│ ├── dao/ # DAO(XxxDao)
|
|
45
|
+
│ ├── cache/ # 缓存(XxxCache)
|
|
46
|
+
│ ├── storage/ # 对象存储(XxxStorage)
|
|
47
|
+
│ ├── dataObject/ # 持久化对象(XxxDO)
|
|
48
|
+
│ └── converter/ # 转换器(XxxConverter)
|
|
49
|
+
│ └── XxxRepository.java # 仓储实现(XxxRepository)
|
|
50
|
+
├── external/
|
|
51
|
+
│ └── [外部中心名称]/
|
|
52
|
+
│ ├── dto/ # 外部 DTO(XxxReqDTO / XxxRespDTO)
|
|
53
|
+
│ ├── converter/ # 防腐转换(XxxConverter)
|
|
54
|
+
│ ├── feign/ # Feign 客户端(IXxxFeignClient)
|
|
55
|
+
│ ├── error/ # 错误码(ExternalErrorEnum)
|
|
56
|
+
│ └── properties/
|
|
57
|
+
│ └── XxxExternalService.java # 外部服务实现
|
|
58
|
+
└── boot/ # 启动层(包名固定:[基础包名].boot)
|
|
59
|
+
└── XxxApplication.java # 启动类
|
|
@@ -26,6 +26,7 @@ build:
|
|
|
26
26
|
repomix: false
|
|
27
27
|
enableBaselineExtract: false
|
|
28
28
|
strictInputConfirm: false
|
|
29
|
+
# convertTimeoutSec: 900 # build 自动 convert 超时(秒),默认 900(15 分钟)
|
|
29
30
|
generateWiki: false
|
|
30
31
|
wikiLang: zh
|
|
31
32
|
force: false
|
|
@@ -55,6 +56,7 @@ convert:
|
|
|
55
56
|
- ./docs/*.pdf
|
|
56
57
|
output: ./my-app-harness
|
|
57
58
|
type: requirements
|
|
59
|
+
# timeoutSec: 900 # 单文件转换超时(秒),默认 900(15 分钟)
|
|
58
60
|
yes: true
|
|
59
61
|
|
|
60
62
|
# wiki:对任意代码工程目录生成 baseline wiki(独立于 harness 生命周期)
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.resolveLaunchScriptPath = resolveLaunchScriptPath;
|
|
7
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
/**
|
|
10
|
-
* Resolve absolute path to bin/launch-codechat-cli.js in the installed package.
|
|
11
|
-
*/
|
|
12
|
-
function resolveLaunchScriptPath() {
|
|
13
|
-
// dist/lib/launch-script-path.js → ../../bin/launch-codechat-cli.js
|
|
14
|
-
const fromDist = path_1.default.resolve(__dirname, '..', '..', 'bin', 'launch-codechat-cli.js');
|
|
15
|
-
if (fs_extra_1.default.existsSync(fromDist)) {
|
|
16
|
-
return fromDist;
|
|
17
|
-
}
|
|
18
|
-
// fallback: package root from scripts/postinstall.js context
|
|
19
|
-
const fromCwd = path_1.default.resolve(__dirname, '..', '..', '..', 'bin', 'launch-codechat-cli.js');
|
|
20
|
-
if (fs_extra_1.default.existsSync(fromCwd)) {
|
|
21
|
-
return fromCwd;
|
|
22
|
-
}
|
|
23
|
-
throw new Error(`未找到 launch-codechat-cli.js(预期:${fromDist})`);
|
|
24
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
# ============================================================
|
|
2
|
-
# CodeChat接口
|
|
3
|
-
# ============================================================
|
|
4
|
-
ANTHROPIC_AUTH_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVpZHEzNjQwIiwiZXhwIjoxNzg0MTAzODE1fQ.d8BSD1V2_5Kv-gB8OeS5092Jg6XoL63XR2Tocw5S2bs
|
|
5
|
-
ANTHROPIC_BASE_URL=https://aiplus.desaysv.com/chatbot/anthropic
|
|
6
|
-
# ANTHROPIC_BASE_URL=http://127.0.0.1:6008/chatbot/anthropic # 德赛本地调试
|
|
7
|
-
ANTHROPIC_MODEL=deepseek # glm / deepseek
|
|
8
|
-
ANTHROPIC_DEFAULT_HAIKU_MODEL=deepseek # glm / deepseek
|
|
9
|
-
ANTHROPIC_DEFAULT_OPUS_MODEL=deepseek # glm / deepseek
|
|
10
|
-
API_TIMEOUT_MS=3000000
|
|
11
|
-
|
|
12
|
-
# ============================================================
|
|
13
|
-
# OpenAI(通过 LiteLLM 代理)
|
|
14
|
-
# 先启动: litellm --config litellm_config.yaml --port 4000
|
|
15
|
-
# ============================================================
|
|
16
|
-
# ANTHROPIC_AUTH_TOKEN=sk-anything
|
|
17
|
-
# ANTHROPIC_BASE_URL=http://localhost:4000
|
|
18
|
-
# ANTHROPIC_MODEL=gpt-4o
|
|
19
|
-
# ANTHROPIC_DEFAULT_SONNET_MODEL=gpt-4o
|
|
20
|
-
# ANTHROPIC_DEFAULT_HAIKU_MODEL=gpt-4o
|
|
21
|
-
# ANTHROPIC_DEFAULT_OPUS_MODEL=gpt-4o
|
|
22
|
-
# API_TIMEOUT_MS=3000000
|
|
23
|
-
|
|
24
|
-
# ============================================================
|
|
25
|
-
# DeepSeek(通过 LiteLLM 代理)
|
|
26
|
-
# 先启动: litellm --config litellm_config.yaml --port 4000
|
|
27
|
-
# ============================================================
|
|
28
|
-
# ANTHROPIC_AUTH_TOKEN=sk-anything
|
|
29
|
-
# ANTHROPIC_BASE_URL=http://localhost:4000
|
|
30
|
-
# ANTHROPIC_MODEL=deepseek-chat
|
|
31
|
-
# ANTHROPIC_DEFAULT_SONNET_MODEL=deepseek-chat
|
|
32
|
-
# ANTHROPIC_DEFAULT_HAIKU_MODEL=deepseek-chat
|
|
33
|
-
# ANTHROPIC_DEFAULT_OPUS_MODEL=deepseek-chat
|
|
34
|
-
# API_TIMEOUT_MS=3000000
|
|
35
|
-
|
|
36
|
-
# ============================================================
|
|
37
|
-
# OpenRouter(直连 Anthropic 兼容接口)
|
|
38
|
-
# ============================================================
|
|
39
|
-
# ANTHROPIC_AUTH_TOKEN=sk-or-v1-xxx
|
|
40
|
-
# ANTHROPIC_BASE_URL=https://openrouter.ai/api/v1
|
|
41
|
-
# ANTHROPIC_MODEL=openai/gpt-4o
|
|
42
|
-
# ANTHROPIC_DEFAULT_SONNET_MODEL=openai/gpt-4o
|
|
43
|
-
# ANTHROPIC_DEFAULT_HAIKU_MODEL=openai/gpt-4o-mini
|
|
44
|
-
# ANTHROPIC_DEFAULT_OPUS_MODEL=openai/gpt-4o
|
|
45
|
-
|
|
46
|
-
# ============================================================
|
|
47
|
-
# 德赛调试专用
|
|
48
|
-
# ============================================================
|
|
49
|
-
CLAUDE_CODE_TRACE_ENABLED=0
|
|
50
|
-
CLAUDE_CODE_TRACE_PIPELINE=0
|
|
51
|
-
CLAUDE_CODE_TRACE_PIPELINE_FILE=
|
|
52
|
-
CLAUDE_CODE_TRACE_WIRE_PARAMS=0
|
|
53
|
-
|
|
54
|
-
# ============================================================
|
|
55
|
-
# 通用设置(建议始终开启)
|
|
56
|
-
# ============================================================
|
|
57
|
-
DISABLE_TELEMETRY=1
|
|
58
|
-
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
|
|
59
|
-
ENABLE_TOOL_SEARCH=0
|