WeKnora deployment source with the reviewed wiki identity, summary and recovery fixes
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/Tencent/WeKnora/internal/agent/skills"
|
||||
"github.com/Tencent/WeKnora/internal/sandbox"
|
||||
)
|
||||
|
||||
// Session skill trees are snapshotted read-only (root-owned, mode 555). uv
|
||||
// venv often has no pip. Skills that lazily pip-install extras on first use
|
||||
// cannot write that venv; session agents must use the /workspace overlay
|
||||
// instead of chown / ensurepip / pip into /opt/weknora/tenant/skills.
|
||||
//
|
||||
// That rule is enforced by the filesystem, not by inspecting commands: the
|
||||
// kernel already refuses the write. What the model needs is a readable reason
|
||||
// for the EROFS / EPERM / "No module named pip" it gets back, which is what
|
||||
// the hints below attach after the fact. An up-front command blacklist was
|
||||
// tried and removed: matching `pip install` next to the skills root also
|
||||
// rejected the recovery command this guidance recommends (installing into the
|
||||
// overlay with `-r <skill>/requirements.txt`), while any indirection through a
|
||||
// shell variable walked straight past it.
|
||||
|
||||
func frozenSkillTreeGuidance(skillName string) string {
|
||||
pkgDir := sandbox.SessionSkillPackageDir(skillName)
|
||||
skillArg := "skill_name=<skill>"
|
||||
if skillName != "" {
|
||||
skillArg = "skill_name=" + strconv.Quote(skillName)
|
||||
}
|
||||
return "the skill tree under " + sandbox.SkillsImageRoot +
|
||||
" is frozen after install (read-only, root-owned; uv venv often has no pip). " +
|
||||
"Do not chown, chmod, ensurepip, or pip/npm install into it. " +
|
||||
"On-demand extras (python-docx, python-pptx, …) go in the session overlay: " +
|
||||
"`python3 -m pip install --target " + pkgDir + " <package>` " +
|
||||
"(system python3, not the skill venv), then execute_skill_script(" + skillArg + "). " +
|
||||
"Or ask the user to reinstall the skill so extras are baked into the image."
|
||||
}
|
||||
|
||||
func isFrozenSkillVenvFailure(stderr string) bool {
|
||||
if stderr == "" {
|
||||
return false
|
||||
}
|
||||
lower := strings.ToLower(stderr)
|
||||
if strings.Contains(stderr, "No module named pip") ||
|
||||
strings.Contains(stderr, "No module named 'pip'") {
|
||||
return true
|
||||
}
|
||||
if strings.Contains(lower, "read-only file system") ||
|
||||
strings.Contains(lower, "erofs") ||
|
||||
strings.Contains(lower, "read-only filesystem") {
|
||||
return true
|
||||
}
|
||||
return strings.Contains(lower, "permission denied") && strings.Contains(lower, ".venv")
|
||||
}
|
||||
|
||||
func skillOnDemandInstallHint(skillName, scriptPath, stdout, stderr string) string {
|
||||
installer := skills.IsOnDemandInstallerPath(scriptPath)
|
||||
failedInstaller := installer &&
|
||||
(isFrozenSkillVenvFailure(stderr) || strings.Contains(strings.ToLower(stdout+stderr), "安装失败") ||
|
||||
strings.Contains(strings.ToLower(stdout+stderr), "install failed"))
|
||||
if !failedInstaller && !isFrozenSkillVenvFailure(stderr) {
|
||||
return ""
|
||||
}
|
||||
msg := "Hint: " + frozenSkillTreeGuidance(skillName)
|
||||
if installer {
|
||||
msg += " Skip this installer and run the skill's real script."
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
func skillMissingPackageHint(skillName, stderr string) string {
|
||||
if !isMissingInterpreterModule(stderr) {
|
||||
return ""
|
||||
}
|
||||
return "Hint: this skill's frozen venv does not have that package. " +
|
||||
frozenSkillTreeGuidance(skillName)
|
||||
}
|
||||
Reference in New Issue
Block a user