Skip to content
Merged

0.2.37 #1130

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
04f7438
feat(explore_agent): enhance tool descriptions and establish explorat…
XingYu-Zhong Aug 7, 2026
2a24198
feat: implement thread snapshot caching and state management
XingYu-Zhong Aug 7, 2026
c5596d1
feat(chromium-cookies): add cookie reading and decryption functionali…
XingYu-Zhong Aug 7, 2026
23793f7
feat: add tool cancellation functionality
XingYu-Zhong Aug 7, 2026
298601b
refactor: simplify telemetry pressure management and improve model re…
XingYu-Zhong Aug 7, 2026
efb8e73
feat: add timing metrics for usage tracking
XingYu-Zhong Aug 7, 2026
b7a6677
feat: enhance speech-to-text settings with credential readiness check…
XingYu-Zhong Aug 7, 2026
4a748d0
feat: enhance model handling by preventing empty primary model from o…
XingYu-Zhong Aug 7, 2026
689e086
fix(office): soft-fail WPS schema validate on intake
XingYu-Zhong Aug 7, 2026
365583e
fix(providers): keep Token Plan catalog across registry races
XingYu-Zhong Aug 7, 2026
b06d4a9
fix(runtime): recover shared Kun when discovery PID is dead
XingYu-Zhong Aug 7, 2026
230e64e
feat: implement preserveRedactedProviderCredentials function and add …
XingYu-Zhong Aug 7, 2026
4f5352d
Merge pull request #1123 from KunAgent/codex/fix-office-wps-schema-in…
XingYu-Zhong Aug 7, 2026
cb1819e
Merge pull request #1125 from KunAgent/codex/fix-shared-runtime-dead-…
XingYu-Zhong Aug 7, 2026
ccfc194
Merge pull request #1124 from KunAgent/codex/fix-tokenplan-model-cata…
XingYu-Zhong Aug 7, 2026
0d7f06f
feat: add in-place update handling and cleanup for automatic updates
XingYu-Zhong Aug 7, 2026
ee678c6
fix(models-dev-catalog): add MiniMax OpenAI-compatible /v1 endpoint a…
XingYu-Zhong Aug 7, 2026
9d900b9
fix(graph): preserve completion-ready runs on lead settlement (#1127)
XingYu-Zhong Aug 7, 2026
6de7210
fix(graph): add thread ownership gate and independent SSE observer (#…
XingYu-Zhong Aug 7, 2026
0f750f3
fix(scripts): ensure proper execution of .cmd scripts on Windows by u…
XingYu-Zhong Aug 7, 2026
278335d
fix: normalize Codex responses URL and update related endpoint handling
XingYu-Zhong Aug 7, 2026
bec9c87
fix: enhance explore_agent tool provider with dynamic advertising bas…
XingYu-Zhong Aug 7, 2026
e17a2f0
fix(cursor): re-expose Kun-exclusive tools and exclude overlapping Cu…
XingYu-Zhong Aug 7, 2026
1b0884d
feat: add explore functionality with new components and tests
XingYu-Zhong Aug 7, 2026
bdb1323
feat: implement ExplorePeekBody component and related tests; enhance …
XingYu-Zhong Aug 7, 2026
5461fc3
feat: add explore_agent tool with read-only access; update related te…
XingYu-Zhong Aug 7, 2026
47613b2
feat: enhance OpenCode Go cookie handling and diagnostics
XingYu-Zhong Aug 7, 2026
b5093ba
feat: enhance explore_agent handling in tool dispatch policy and mess…
XingYu-Zhong Aug 7, 2026
818a917
feat: release v0.2.37 with enhancements to explore_agent, Agent Graph…
XingYu-Zhong Aug 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion build/installer.nsh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Var /GLOBAL KunInstallerPreserveOtherScope
Var /GLOBAL KunInstallerOtherUninstallString
Var /GLOBAL KunInstallerOtherQuietUninstallString
Var /GLOBAL KunInstallerRestoreInteractive
Var /GLOBAL KunInstallerInPlaceUpdate
Var /GLOBAL KunInstallerCurrentUserShortcutName
Var /GLOBAL KunInstallerCurrentUserMenuDirectory
!endif
Expand Down Expand Up @@ -77,6 +78,7 @@ Var /GLOBAL KunInstallerStopResult
StrCpy $KunInstallerOtherQuietUninstallString ""
!ifndef BUILD_UNINSTALLER
StrCpy $KunInstallerRestoreInteractive 0
StrCpy $KunInstallerInPlaceUpdate 0
!endif

${if} ${isUpdated}
Expand Down Expand Up @@ -157,7 +159,14 @@ Var /GLOBAL KunInstallerStopResult
!macroend

!macro customUnInstallCheck
${if} $KunInstallerPrimarySourceStale != 1
${if} $KunInstallerInPlaceUpdate == 1
# Same-directory automatic updates overwrite in place. Running the old
# uninstaller or FallbackCleanup first can empty the program directory when
# the subsequent extract/validate step fails.
ClearErrors
StrCpy $R0 0
DetailPrint "In-place automatic update; skipping pre-install removal of $KunInstallerPrimarySourceDir."
${elseIf} $KunInstallerPrimarySourceStale != 1
StrCpy $KunInstallerSourceDir $KunInstallerPrimarySourceDir
Call KunHandleOldUninstallerResult
${else}
Expand Down Expand Up @@ -214,6 +223,13 @@ Var /GLOBAL KunInstallerStopResult
Quit
${endif}

${if} $KunInstallerInPlaceUpdate == 1
!insertmacro kunRunMigrationHelper CleanupInPlaceLeftovers
${if} $KunInstallerHelperExitCode != 0
DetailPrint "Kun could not remove obsolete in-place update leftovers: $KunInstallerHelperOutput"
${endif}
${endif}

!insertmacro kunRunMigrationHelper UpdatePath
${if} $KunInstallerHelperExitCode != 0
DetailPrint "Kun could not update the user PATH: $KunInstallerHelperOutput"
Expand Down Expand Up @@ -256,6 +272,7 @@ Var /GLOBAL KunInstallerStopResult
System::Call 'kernel32::SetEnvironmentVariable(t, t)i ("KUN_INSTALLER_PRIMARY_SOURCE_STALE", "$KunInstallerPrimarySourceStale").r0'
System::Call 'kernel32::SetEnvironmentVariable(t, t)i ("KUN_INSTALLER_SECONDARY_SOURCE_STALE", "$KunInstallerSecondarySourceStale").r0'
System::Call 'kernel32::SetEnvironmentVariable(t, t)i ("KUN_INSTALLER_CANDIDATE_EXPLICIT", "$KunInstallerCandidateExplicit").r0'
System::Call 'kernel32::SetEnvironmentVariable(t, t)i ("KUN_INSTALLER_IN_PLACE_UPDATE", "$KunInstallerInPlaceUpdate").r0'
System::Call 'kernel32::SetEnvironmentVariable(t, t)i ("KUN_INSTALLER_INSTALL_MODE", "$installMode").r0'
FunctionEnd

Expand Down Expand Up @@ -528,6 +545,7 @@ Var /GLOBAL KunInstallerStopResult
Call KunRetireSelectedShellState
${else}
StrCpy $KunInstallerSourceDir $KunInstallerPrimarySourceDir
Call KunMarkInPlaceAutomaticUpdate
Call KunSecureSelectedUninstallRegistration
${endif}
${if} $KunInstallerHelperOutput == "2"
Expand All @@ -543,6 +561,20 @@ Var /GLOBAL KunInstallerStopResult
StrCpy $KunInstallerMigrationPrepared 1
FunctionEnd

Function KunMarkInPlaceAutomaticUpdate
StrCpy $KunInstallerInPlaceUpdate 0
${ifNot} ${isUpdated}
Return
${endif}
${if} $KunInstallerPrimarySourceDir == ""
Return
${endif}
${if} $KunInstallerPrimarySourceDir == $KunInstallerTargetDir
StrCpy $KunInstallerInPlaceUpdate 1
DetailPrint "Automatic update will overwrite $KunInstallerTargetDir in place without pre-deleting the application payload."
${endif}
FunctionEnd

Function KunSuspendCurrentUserUninstallRegistration
ReadRegStr $KunInstallerOtherUninstallString HKEY_CURRENT_USER "${UNINSTALL_REGISTRY_KEY}" UninstallString
ReadRegStr $KunInstallerOtherQuietUninstallString HKEY_CURRENT_USER "${UNINSTALL_REGISTRY_KEY}" QuietUninstallString
Expand Down Expand Up @@ -575,6 +607,14 @@ Var /GLOBAL KunInstallerStopResult
FunctionEnd

Function KunSecureSelectedUninstallRegistration
${if} $KunInstallerInPlaceUpdate == 1
# Hide the old uninstaller from electron-builder so it cannot wipe the
# same directory before the new payload is written and validated.
DeleteRegValue SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" UninstallString
DeleteRegValue SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" QuietUninstallString
DetailPrint "In-place automatic update; suppressed the selected-scope uninstaller until the new payload is installed."
Return
${endif}
Call KunResolveTrustedUninstaller
${if} $KunInstallerHelperOutput == ""
DeleteRegValue SHELL_CONTEXT "${UNINSTALL_REGISTRY_KEY}" UninstallString
Expand Down
92 changes: 91 additions & 1 deletion build/windows-installer-migration.ps1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
param(
[Parameter(Mandatory = $true)]
[ValidateSet('ResolvePath', 'ResolveSource', 'ResolveUpdateScope', 'ResolveUninstaller', 'StopProcesses', 'Recover', 'Prepare', 'FallbackCleanup', 'Restore', 'ValidatePayload', 'UpdatePath')]
[ValidateSet('ResolvePath', 'ResolveSource', 'ResolveUpdateScope', 'ResolveUninstaller', 'StopProcesses', 'Recover', 'Prepare', 'FallbackCleanup', 'Restore', 'ValidatePayload', 'CleanupInPlaceLeftovers', 'UpdatePath')]
[string]$Action,
[string]$ResultPath = ''
)
Expand Down Expand Up @@ -939,6 +939,93 @@ function Assert-PackagedInstallPayload {
) 'the unpacked Kun service manager entry'
}

function Test-InPlaceUpdateRequested {
return [string]::Equals(
(Get-EnvironmentValue 'KUN_INSTALLER_IN_PLACE_UPDATE').Trim(),
'1',
[StringComparison]::Ordinal
)
}

function Get-CurrentProductUninstallerFile {
$configured = (Get-EnvironmentValue 'KUN_INSTALLER_PRODUCT_NAME').Trim()
if (-not [string]::IsNullOrWhiteSpace($configured)) {
return 'Uninstall ' + $configured + '.exe'
}
return 'Uninstall ' + (Get-CanonicalLeaf) + '.exe'
}

function Test-RetainedInPlaceKnownEntry([IO.FileSystemInfo]$Entry) {
if ($Entry.PSIsContainer) {
# Keep packaged directories that the new payload still uses.
return @('resources', 'locales', 'bin') -contains $Entry.Name.ToLowerInvariant()
}

$expectedExecutable = Get-ExpectedApplicationExecutable
if ([string]::Equals($Entry.Name, $expectedExecutable, [StringComparison]::OrdinalIgnoreCase)) {
return $true
}

$currentUninstaller = Get-CurrentProductUninstallerFile
if ([string]::Equals($Entry.Name, $currentUninstaller, [StringComparison]::OrdinalIgnoreCase)) {
return $true
}

# Electron runtime files from the newly extracted package stay in place.
$runtimeFiles = @(
'uninstallericon.ico',
'chrome_100_percent.pak',
'chrome_200_percent.pak',
'd3dcompiler_47.dll',
'dxcompiler.dll',
'dxil.dll',
'ffmpeg.dll',
'icudtl.dat',
'libegl.dll',
'libglesv2.dll',
'license.electron.txt',
'licenses.chromium.html',
'resources.pak',
'snapshot_blob.bin',
'v8_context_snapshot.bin',
'vk_swiftshader.dll',
'vk_swiftshader_icd.json',
'vulkan-1.dll'
)
return $runtimeFiles -contains $Entry.Name.ToLowerInvariant()
}

function Invoke-CleanupInPlaceLeftovers {
if (-not (Test-InPlaceUpdateRequested)) {
return
}

$target = Normalize-FullPath (Get-EnvironmentValue 'KUN_INSTALLER_TARGET')
$source = Normalize-FullPath (Get-EnvironmentValue 'KUN_INSTALLER_SOURCE')
if ([string]::IsNullOrWhiteSpace($target)) {
throw 'KUN_INSTALLER_TARGET is required for in-place leftover cleanup.'
}
if (-not [string]::IsNullOrWhiteSpace($source) -and -not (Test-PathEqual $source $target)) {
throw "In-place leftover cleanup requires the source and target to match: $source -> $target"
}

Assert-PackagedInstallPayload

$legacyEntries = @(Get-ChildItem -LiteralPath $target -Force | Where-Object {
(Test-KnownApplicationEntry $_) -and -not (Test-RetainedInPlaceKnownEntry $_)
})
foreach ($entry in $legacyEntries) {
if ($entry.PSIsContainer) {
Assert-NoReparsePointsInTree $entry 'Obsolete in-place application directory'
} elseif (Test-ReparsePoint $entry.FullName) {
throw "Obsolete in-place application file is a reparse point: $($entry.FullName)"
}
}
foreach ($entry in $legacyEntries) {
Remove-KnownApplicationEntry $entry
}
}

function Test-AppSpecificUninstaller([string]$Source) {
if ([string]::IsNullOrWhiteSpace($Source)) {
return $false
Expand Down Expand Up @@ -1384,6 +1471,9 @@ try {
'ValidatePayload' {
Assert-PackagedInstallPayload
}
'CleanupInPlaceLeftovers' {
Invoke-CleanupInPlaceLeftovers
}
'UpdatePath' {
Update-UserPath
}
Expand Down
40 changes: 20 additions & 20 deletions kun/benchmarks/agent-core.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,121 +10,121 @@
"id": "architecture-summary",
"tags": ["smoke", "architecture"],
"prompt": "Read the repository and explain the active Renderer -> preload -> main -> Kun runtime data path. Cite the most relevant file paths. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredTools": ["explore_agent"], "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "runtime-entrypoint",
"tags": ["smoke", "runtime"],
"prompt": "Find the Kun serve-mode composition root and summarize how stores, model clients, tools, and the agent loop are assembled. Cite exact file paths. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "renderer-send-flow",
"tags": ["smoke", "frontend"],
"prompt": "Trace a chat message from the renderer composer through the preload/main bridge to the Kun turn endpoint. Return a concise ordered call path with files. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "sse-replay",
"tags": ["smoke", "runtime"],
"prompt": "Explain how Kun SSE event replay avoids duplicates and cursor rewind after reconnect or restart. Cite the implementation and tests. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "mcp-lifecycle",
"tags": ["smoke", "mcp"],
"prompt": "Inspect MCP startup, tool discovery, execution, and reconnect behavior. Identify the main reliability boundaries and cite the implementation files. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "cache-prefix",
"tags": ["cache"],
"prompt": "Explain what makes Kun's immutable prompt prefix stable and list dynamic data that must remain outside it. Cite code and documentation. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "provider-url-contract",
"tags": ["provider"],
"prompt": "Trace how baseUrl and endpointFormat affect provider URL construction and request bodies across chat and auxiliary model calls. Cite all important consumers. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "attachment-flow",
"tags": ["attachments"],
"prompt": "Trace an image or local file attachment from renderer selection to model input or fallback. Identify the cross-layer contract fields and failure points. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "approval-flow",
"tags": ["runtime", "security"],
"prompt": "Trace a tool approval request from agent loop creation through SSE/UI resolution back to tool execution. Cite routes, gates, and renderer handlers. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "goal-resume",
"tags": ["runtime", "goal"],
"prompt": "Explain how active goals survive runtime restart, how orphaned turns are reconciled, and where auto-resume is triggered. Cite tests if present. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "subagent-permissions",
"tags": ["subagent", "security"],
"prompt": "Explain how subagent tool policies inherit or restrict built-in tools, MCP servers, and skills without escalating the parent permissions. Cite enforcement points. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "settings-persistence",
"tags": ["settings"],
"prompt": "Trace a Kun settings change from renderer state through validation/persistence to managed runtime restart. Highlight rollback behavior. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "test-selection",
"tags": ["quality"],
"prompt": "Identify how the verify_changes tool selects and runs validation after edits. Explain its safety limits and output contract. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "build-pipeline",
"tags": ["build"],
"prompt": "Summarize the development, typecheck, test, build, and packaging pipeline for Kun. Cite package scripts and packaging configuration. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "security-boundaries",
"tags": ["security"],
"prompt": "Map the main trust boundaries for renderer IPC, filesystem tools, command execution, MCP, and secrets. Cite concrete enforcement files. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "runtime-hotspots",
"tags": ["performance"],
"prompt": "Inspect runtime event persistence, SSE replay, tool execution, and context assembly. Identify three evidence-based performance or memory hotspots with file references. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "thread-persistence",
"tags": ["storage"],
"prompt": "Explain how thread/session data is persisted and indexed across file and hybrid SQLite stores, including usage carryover. Cite implementation files. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "model-capabilities",
"tags": ["provider"],
"prompt": "Explain how model capabilities control image input, tool calling, reasoning effort, endpoint format, and context limits. Cite schemas and request construction. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "frontend-chunking",
"tags": ["frontend", "performance"],
"prompt": "Inspect renderer lazy loading and identify which Workbench surfaces are split into separate chunks and which heavy chat dependencies still load eagerly. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
},
{
"id": "failure-recovery",
"tags": ["runtime", "reliability"],
"prompt": "Map how the desktop app detects an unhealthy Kun child, budgets restarts, distinguishes settings restarts from crashes, and reports status to the renderer. Do not modify files.",
"expect": { "requiredAnyTools": ["read", "grep", "find", "ls"] }
"expect": { "requiredAnyTools": ["explore_agent", "read", "grep", "find", "ls"] }
}
]
}
14 changes: 11 additions & 3 deletions kun/src/adapters/model/compat-message-projector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { extractToolResultImages, toolResultTextWithoutImages } from '../../loop
import { wrapUntrustedContent } from '../../security/untrusted-content.js'
import {
COMPAT_ANTHROPIC_THINKING,
COMPAT_TOOL_RESULT_ERROR,
COMPAT_HISTORY_CONTEXT,
type CompatChatMessage,
type CompatChatMessageContentPart
Expand Down Expand Up @@ -248,7 +249,8 @@ class CompatMessageProjector {
return {
role: 'tool',
content: text || '(image omitted: the active model has no image input)',
tool_call_id: item.callId
tool_call_id: item.callId,
...(item.isError === true ? { [COMPAT_TOOL_RESULT_ERROR]: true } : {})
}
}
const parts: CompatChatMessageContentPart[] = []
Expand All @@ -259,12 +261,18 @@ class CompatMessageProjector {
image_url: { url: `data:${image.mimeType};base64,${image.dataBase64}` }
})
}
return { role: 'tool', content: parts, tool_call_id: item.callId }
return {
role: 'tool',
content: parts,
tool_call_id: item.callId,
...(item.isError === true ? { [COMPAT_TOOL_RESULT_ERROR]: true } : {})
}
}
return {
role: 'tool',
content: toolResultContent(item.output),
tool_call_id: item.callId
tool_call_id: item.callId,
...(item.isError === true ? { [COMPAT_TOOL_RESULT_ERROR]: true } : {})
}
}

Expand Down
Loading
Loading