This is an automated email from the ASF dual-hosted git repository.

hsluoyz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/casbin-gateway.git


The following commit(s) were added to refs/heads/master by this push:
     new a56a30e  fix(agent): see the agent npx runs from its cache
a56a30e is described below

commit a56a30ea70a0315555b3fa4c08276ba42f94352a
Author: Yang Luo <[email protected]>
AuthorDate: Sun Aug 23 21:21:11 2026 +0800

    fix(agent): see the agent npx runs from its cache
---
 agent/fingerprint_load_test.go   |  2 +-
 agent/fingerprints/dsh.json      |  6 ++++++
 agent/scan_unix.go               |  3 +++
 agent/scan_windows.go            |  3 +++
 agentprocess/process.go          | 32 ++++++++++++++++++++++++++++++--
 web/src/components/AgentIcon.tsx |  1 +
 6 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/agent/fingerprint_load_test.go b/agent/fingerprint_load_test.go
index 14fca08..aed8072 100644
--- a/agent/fingerprint_load_test.go
+++ b/agent/fingerprint_load_test.go
@@ -23,7 +23,7 @@ import (
 func TestFingerprintsLoad(t *testing.T) {
        want := []string{
                "claude-code", "claude-desktop", "codex-cli", "codex", 
"cursor-agent",
-               "cursor", "openagent", "openclaw", "windsurf",
+               "cursor", "dsh", "openagent", "openclaw", "windsurf",
        }
 
        loaded, err := loadFingerprints(fingerprintFS)
diff --git a/agent/fingerprints/dsh.json b/agent/fingerprints/dsh.json
new file mode 100644
index 0000000..daf8fd4
--- /dev/null
+++ b/agent/fingerprints/dsh.json
@@ -0,0 +1,6 @@
+{
+  "id": "dsh",
+  "displayName": "DeepSeek Harness",
+  "execName": "dsh",
+  "npmPackage": "@deepseek-ai/dsh"
+}
diff --git a/agent/scan_unix.go b/agent/scan_unix.go
index ca8e58c..3e7e780 100644
--- a/agent/scan_unix.go
+++ b/agent/scan_unix.go
@@ -69,6 +69,9 @@ func userNpmPatterns(fingerprint *Fingerprint, home string) 
[]string {
                filepath.Join(home, ".asdf", "installs", "nodejs", "*", "lib", 
"node_modules", pkg, "package.json"),
                // pnpm groups its global packages under a store layout version.
                filepath.Join(home, ".local", "share", "pnpm", "global", "*", 
"node_modules", pkg, "package.json"),
+               // An agent whose documented command is "npx <package>" is never
+               // installed globally; the copy npx keeps in npm's cache is the 
install.
+               filepath.Join(home, ".npm", "_npx", "*", "node_modules", pkg, 
"package.json"),
        }
        for _, dir := range fingerprint.ExtraUnixNpmDirs {
                patterns = append(patterns, filepath.Join(home, 
filepath.FromSlash(dir), "node_modules", pkg, "package.json"))
diff --git a/agent/scan_windows.go b/agent/scan_windows.go
index ae30d36..14db6e0 100644
--- a/agent/scan_windows.go
+++ b/agent/scan_windows.go
@@ -324,6 +324,9 @@ func scanWindowsNpm(ctx context.Context, fingerprint 
*Fingerprint, home homeDir)
                filepath.Join(local, "Volta", "tools", "image", "packages", 
pkg, "lib", "node_modules", pkg, "package.json"),
                // pnpm groups its global packages under a store layout version.
                filepath.Join(local, "pnpm", "global", "*", "node_modules", 
pkg, "package.json"),
+               // An agent whose documented command is "npx <package>" is never
+               // installed globally; the copy npx keeps in npm's cache is the 
install.
+               filepath.Join(local, "npm-cache", "_npx", "*", "node_modules", 
pkg, "package.json"),
        }
        for _, dir := range fingerprint.ExtraWindowsNpmDirs {
                patterns = append(patterns, filepath.Join(local, 
filepath.FromSlash(dir), "node_modules", pkg, "package.json"))
diff --git a/agentprocess/process.go b/agentprocess/process.go
index ed68afc..e4c50a4 100644
--- a/agentprocess/process.go
+++ b/agentprocess/process.go
@@ -235,8 +235,36 @@ func containsPath(command, path string) bool {
                return false
        }
        path = filepath.Clean(path)
+       if textContains(command, path) {
+               return true
+       }
+       // A shim reaches its target through its own directory, so the command 
line
+       // spells the file with a relative hop the recorded installation has 
not.
+       for _, argument := range commandArguments(command) {
+               if textContains(filepath.Clean(argument), path) {
+                       return true
+               }
+       }
+       return false
+}
+
+func textContains(text, path string) bool {
        if runtime.GOOS == "windows" {
-               return strings.Contains(strings.ToLower(command), 
strings.ToLower(path))
+               return strings.Contains(strings.ToLower(text), 
strings.ToLower(path))
+       }
+       return strings.Contains(text, path)
+}
+
+// commandArguments splits a command line the way its quoting reads, so an
+// argument holding a path with spaces stays one string.
+func commandArguments(command string) []string {
+       var arguments []string
+       for i, part := range strings.Split(command, `"`) {
+               if i%2 == 1 {
+                       arguments = append(arguments, part)
+                       continue
+               }
+               arguments = append(arguments, strings.Fields(part)...)
        }
-       return strings.Contains(command, path)
+       return arguments
 }
diff --git a/web/src/components/AgentIcon.tsx b/web/src/components/AgentIcon.tsx
index b810d5c..eb62fd7 100644
--- a/web/src/components/AgentIcon.tsx
+++ b/web/src/components/AgentIcon.tsx
@@ -26,6 +26,7 @@ const agentSites: Record<string, string> = {
   "Cursor Agent": "cursor.com",
   Windsurf: "windsurf.com",
   OpenAgent: "openagentai.org",
+  "DeepSeek Harness": "deepseek.com",
 };
 
 const agentKey = (agent: unknown) =>


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to