Class ::nsmcp::CodeUpstreamTool (public)

 ::nx::Class ::nsmcp::CodeUpstreamTool[i]

Defined in /usr/local/ns/tcl/nsmcp/code-upstream.tcl

Testcases:
No testcase defined.
Source code:
    :property {name code_upstream_compare}
    :property {permission diagnostics.code.read}
    :property {description {Compare an installed Tcl/NX/XOTcl procedure or method with literal source declarations in administrator-mapped public GitHub repositories. Returns immutable commit/file links, body and argument comparisons, bounded source excerpts and recent file commits. Optional configured baseline distinguishes differences from a declared installation baseline; differences alone do not prove a bug or an upstream fix. Never evaluates remote code or sends local source to GitHub. Requires enableCodeTools and enableCodeUpstream. Unsupported/dynamic/ambiguous source is unavailable, never equal.}}
    :property {inputSchema {{"type":"object","properties":{"name":{"type":"string"},"ref":{"type":"string","description":"Optional branch, tag or commit within the configured repository; defaults to the mapping ref."}},"required":["name"],"additionalProperties":false}}}
    :public method describe {} {
        set description [next]; set fields {}
        foreach {key type value} [lindex $description 2] {
            if {$key eq "annotations"} {
                set value {readOnlyHint boolean true destructiveHint boolean false openWorldHint boolean true}
            }
            lappend fields $key $type $value
        }
        return [list {} object $fields]
    }
    :method options {arguments} {
        set opts {name {} ref {}}
        foreach {key value} [:jsonArguments $arguments] {dict set opts [string range $key 1 end] $value}
        if {[dict get $opts name] eq {} || [string length [dict get $opts name]]>1024 || [regexp {[\x00\r\n]} [dict get $opts name]]} {error "Invalid definition name"}
        if {[dict get $opts ref] ne {}} {::nsmcp::codeUpstreamRef [dict get $opts ref]}
        return $opts
    }
    :public method validate {arguments} {
        if {[catch {:options $arguments} message]} {return -code error -errorcode {NSMCP RPC -32602} $message}
    }
    :method mappings {} {return [ns_config ns/server/[ns_info server]/module/nsmcp codeUpstreamMappings {}]}
    :method http {url accept} {
        set headers [ns_set create Accept $accept User-Agent nsmcp-code-upstream Accept-Encoding identity X-GitHub-Api-Version 2022-11-28]
        try {
            # No redirect following, cookies, bearer token or arbitrary URL.
            # Fail closed on runtimes without bounded response support.
            set reply [ns_http run -method GET -headers $headers -binary -timeout 3s -expire 5s -maxresponse 1MiB $url]
            try {
                if {[dict get $reply status]==200} {
                    set bytes [dict get $reply body]
                    set decoded [encoding convertfrom utf-8 $bytes]
                    if {[encoding convertto utf-8 $decoded] ne $bytes} {error "invalid-upstream-utf8"}
                    dict set reply body $decoded
                }
                return [dict remove $reply headers]
            } finally {
                if {[dict exists $reply headers]} {ns_set free [dict get $reply headers]}
            }
        } finally {ns_set free $headers}
    }
    :method get {endpoint accept} {
        if {![regexp {^/repos/[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+/(commits|contents)(/|\?)} $endpoint] || [regexp {[\r\n]} $endpoint]} {error "invalid-github-endpoint"}
        if {[incr :requests]>5} {error "upstream-request-limit"}
        set url https://api.github.com$endpoint
        # Small successful-response cache, server-local and size bounded.
        set cache nsmcp:upstream-cache:[ns_info server]
        set key [ns_crypto::md string -digest sha256 -- [list $url $accept]]
        if {[nsv_exists $cache $key]} {
            set cached [nsv_get $cache $key]
            if {[clock seconds]-[dict get $cached at]<60} {return [dict get $cached body]}
        }
        if {[catch {:http $url $accept} reply]} {error "github-transport-failed"}
        set status [dict get $reply status]
        if {$status!=200} {error "github-http-$status"}
        set body [dict get $reply body]
        if {[string bytelength $body]>1048576} {error "github-response-too-large"}
        if {[llength [nsv_array names $cache]]>=16} {nsv_unset -nocomplain $cache}
        nsv_set $cache $key [dict create at [clock seconds] body $body]
        return $body
    }
    :method commit {repo ref} {
        set ref [ns_urlencode $ref]
        set sha [string trim [:get /repos/$repo/commits/$ref application/vnd.github.sha]]
        if {![regexp {^[a-f0-9]{40}$} $sha]} {error "invalid-github-commit"}
        return $sha
    }
    :method source {repo sha path} {
        set encoded {}; foreach segment [split $path /] {lappend encoded [ns_urlencode $segment]}
        return [:get /repos/$repo/contents/[join $encoded /]?ref=$sha application/vnd.github.raw+json]
    }
    :method comparison {local remote} {
        set args [::nsmcp::codeCanonicalArguments [dict get $remote arguments]]
        set body [dict get $remote body]
        set sameArgs [expr {[dict get $local arguments] eq $args}]
        set sameBody [expr {[dict get $local body] eq $body}]
        set normalized [expr {[dict exists $local comparisonBody] ? [dict get $local comparisonBody] : [dict get $local body]}]
        set normalizedSame [expr {$normalized eq $body}]
        return [list identical boolean [expr {$sameArgs && $sameBody}] argumentsIdentical boolean $sameArgs bodyIdentical boolean $sameBody normalizedIdentical boolean [expr {$sameArgs && $normalizedSame}] normalizedBodyIdentical boolean $normalizedSame bodySha256 string [ns_crypto::md string -digest sha256 -- $body] arguments string [string range $args 0 4095] argumentsTruncated boolean [expr {[string length $args]>4096}]]
    }
    :method selectDefinition {source name local} {
        set state [::nsmcp::codeStaticDefinitions $source $name]
        set candidates [dict get $state matches]
        set conditional false
        foreach candidate $candidates {if {[llength [dict get $candidate conditions]]} {set conditional true}}
        if {[llength $candidates]>1 && !$conditional} {error "upstream-definition-missing-or-ambiguous"}
        if {!$conditional} {
            return [dict create selected true selection unique-literal-declaration remote [dict merge [lindex $candidates 0] [dict remove $state matches]] candidates $candidates]
        }
        set normalizedMatches {}; set index 0
        foreach candidate $candidates {
            set comparison {}; foreach {key type value} [:comparison $local $candidate] {dict set comparison $key $value}
            if {[dict get $comparison normalizedIdentical]} {lappend normalizedMatches $index}
            incr index
        }
        set matches $normalizedMatches
        if {[llength $matches]!=1} {
            return [dict create selected false selection unresolved-conditional-variants candidates $candidates matchingCandidates $matches]
        }
        set index [lindex $matches 0]
        return [dict create selected true selection matching-loaded-conditional-variant selectedCandidate $index remote [dict merge [lindex $candidates $index] [dict remove $state matches]] candidates $candidates]
    }
    :method candidates {selection local} {
        set rows {}; set i 0; set list [dict get $selection candidates]
        set budget [expr {max(1,8192/[llength $list])}]
        foreach candidate $list {
            set conditions {}; set j 0
            foreach condition [dict get $candidate conditions] {lappend conditions $j string $condition; incr j}
            set body [dict get $candidate body]
            lappend rows $i object [list candidate number $i form string [dict get $candidate form] conditions array $conditions comparison object [:comparison $local $candidate] bodyExcerpt string [string range $body 0 [expr {$budget-1}]] bodyExcerptTruncated boolean [expr {[string length $body]>$budget}]]
            incr i
        }
        return $rows
    }
    :public method execute {context arguments} {
        set opts [:options $arguments]
        try {
            return [:compare $context $opts]
        } on error {message options} {
            # Return a bounded diagnostic, not SQL, transport details or remote
            # response bodies. Unavailable is distinct from an equal comparison.
            set reason upstream-comparison-unavailable
            if {[regexp {^(upstream-[a-z-]+|github-(?:http-[0-9]{3}|transport-failed|response-too-large)|invalid-(?:upstream-[a-z-]+|github-[a-z-]+)|local-(?:source-file-metadata-unavailable|definition-not-scripted))$} $message]} {set reason $message}
            return [list {} object [list available boolean false name string [dict get $opts name] server string [$context server] observedAt number [clock seconds] reason string $reason upstreamFixVerified boolean false comparisonPerformed boolean false]]
        }
    }
    :method compare {context opts} {
        set name [dict get $opts name]
        set doc [::nsmcp::codeMetadata $name]
        if {$doc eq {} && [string first :: $name]==0} {set doc [::nsmcp::codeMetadata [string range $name 2 end]]}
        if {![dict exists $doc script]} {error "local-source-file-metadata-unavailable"}
        set path [string trimleft [dict get $doc script] /]
        set mapping [::nsmcp::codeUpstreamMapping $path [:mappings]]
        set local [::nsmcp::codeLocalComparable $name $doc]
        set localObservedAt [clock seconds]
        set repo [dict get $mapping repository]; set file [dict get $mapping path]
        set ref [dict get $opts ref]; if {$ref eq {}} {set ref [dict get $mapping ref]}
        set :requests 0
        set sha [:commit $repo $ref]
        set source [:source $repo $sha $file]
        set selection [:selectDefinition $source $name $local]
        set candidates [:candidates $selection $local]
        set normalizations {}; set ni 0
        foreach normalization [dict get $local normalizations] {lappend normalizations $ni string $normalization; incr ni}
        if {![dict get $selection selected]} {
            return [list {} object [list available boolean false comparisonPerformed boolean false reason string upstream-conditional-variant-unresolved name string $name sourceFile string $path repository string $repo upstreamPath string $file commit string $sha upstreamUrl string https://github.com/$repo/blob/$sha/$file localDefinitionSha256 string [dict get $local definitionSha256] localNormalizations array $normalizations candidateCount number [llength [dict get $selection candidates]] candidates array $candidates conditionsEvaluated boolean false selectedCandidate null {} matchingCandidateCount number [llength [dict get $selection matchingCandidates]] upstreamFixVerified boolean false limitations string {The loaded definition does not uniquely identify one literal upstream conditional variant. Conditions were not evaluated. Candidate comparisons are evidence, not proof of the active upstream implementation or a local modification.}]]
        }
        set remote [dict get $selection remote]
        set comparison [:comparison $local $remote]
        set baseline {}; set status unknown-no-baseline
        if {[dict exists $mapping baselineRef] && [dict get $mapping baselineRef] ne {}} {
            set baseSha [:commit $repo [dict get $mapping baselineRef]]
            set baseSelection [:selectDefinition [:source $repo $baseSha $file] $name $local]
            if {[dict get $baseSelection selected]} {
                set baseCompare [:comparison $local [dict get $baseSelection remote]]
                set baseDict {}; foreach {k t v} $baseCompare {dict set baseDict $k $v}
                set status [expr {[dict get $baseDict normalizedIdentical] ? "matches-configured-baseline" : "differs-from-configured-baseline"}]
                set baseline [list available boolean true commit string $baseSha url string https://github.com/$repo/blob/$baseSha/$file comparison object $baseCompare]
            } else {
                set status unknown-baseline-variant
                set baseline [list available boolean false reason string upstream-conditional-variant-unresolved commit string $baseSha url string https://github.com/$repo/blob/$baseSha/$file candidates array [:candidates $baseSelection $local]]
            }
        }
        # File history supplies candidates, not proof that each commit changes
        # this procedure or fixes the diagnosed failure.
        set history {}; set historyAvailable true
        if {[catch {
            set records [ns_json parse [:get /repos/$repo/commits?sha=$sha&path=[ns_urlencode $file]&per_page=5 application/vnd.github+json]]
            set i 0
            foreach record [lrange $records 0 4] {
                set hash [dict get $record sha]
                if {![regexp {^[a-f0-9]{40}$} $hash]} {error "invalid-github-commit"}
                set parents {}; set j 0; set parentsAvailable [dict exists $record parents]
                if {$parentsAvailable} {
                    foreach parent [lrange [dict get $record parents] 0 1] {
                        set parentSha [dict get $parent sha]
                        if {![regexp {^[a-f0-9]{40}$} $parentSha]} {error "invalid-github-commit"}
                        lappend parents $j object [list commit string $parentSha url string https://github.com/$repo/commit/$parentSha]
                        incr j
                    }
                }
                set parentsComplete [expr {$parentsAvailable && [llength [dict get $record parents]]<=2}]
                lappend history $i object [list commit string $hash url string https://github.com/$repo/commit/$hash message string [string range [dict get $record commit message] 0 2047] parents array $parents parentsComplete boolean $parentsComplete]
                incr i
            }
        }]} {set historyAvailable false}
        set localBody [dict get $local body]; set remoteBody [dict get $remote body]
        set first 0; set a [split $localBody \n]; set b [split $remoteBody \n]
        while {$first<min([llength $a],[llength $b]) && [lindex $a $first] eq [lindex $b $first]} {incr first}
        set localExcerpt [string range [join [lrange $a [expr {max(0,$first-3)}] [expr {$first+30}]] \n] 0 8191]
        set remoteExcerpt [string range [join [lrange $b [expr {max(0,$first-3)}] [expr {$first+30}]] \n] 0 8191]
        return [list {} object [list available boolean true comparisonPerformed boolean true resolutionCacheSeconds number 60 comparisonScope string literal-source localNormalizations array $normalizations localComparisonBodySha256 string [ns_crypto::md string -digest sha256 -- [dict get $local comparisonBody]] candidateCount number [llength [dict get $selection candidates]] selectedCandidate number [expr {[dict exists $selection selectedCandidate] ? [dict get $selection selectedCandidate] : 0}] candidates array $candidates conditionsEvaluated boolean false server string [$context server] observedAt number [clock seconds] name string $name sourceFile string $path repository string $repo upstreamPath string $file requestedRef string $ref commit string $sha upstreamUrl string https://github.com/$repo/blob/$sha/$file localObservedAt number $localObservedAt localArguments string [dict get $local arguments] localDefinitionSha256 string [dict get $local definitionSha256] localBodySha256 string [ns_crypto::md string -digest sha256 -- $localBody] upstreamFileSha256 string [ns_crypto::md string -digest sha256 -- $source] comparison object $comparison baseline object $baseline localModificationStatus string $status upstreamFixVerified boolean false firstDifferentBodyLine number [expr {$localBody eq $remoteBody ? 0 : $first+1}] excerptStartBodyLine number [expr {max(0,$first-3)+1}] localExcerpt string $localExcerpt upstreamExcerpt string $remoteExcerpt excerptsComplete boolean [expr {$localExcerpt eq $localBody && $remoteExcerpt eq $remoteBody}] extraction object [list form string [dict get $remote form] dynamicCommands number [dict get $remote dynamicCommands] unsupportedCommands number [dict get $remote unsupportedCommands] selection string [dict get $selection selection]] recentFileCommits array $history historyAvailable boolean $historyAvailable historyLimit number 5 diskCompared boolean false limitations string {Conditional selection identifies a unique literal definition matching loaded code; it does not evaluate guards or establish the active implementation in an upstream installation. Raw identical/bodyIdentical comparisons preserve all bytes. normalizedIdentical/normalizedBodyIdentical separately account for explicitly reported NSF-generated preambles. Equality compares exact bodies and canonical argument lists, not semantics or full object state. Generated wrappers, formatting and framework versions can cause differences. A configured baseline is an administrator assertion, not verified installation provenance. File history is bounded and not procedure-specific. Excerpts may omit other changes. An upstream fix requires connecting code changes to the observed failure; commit messages alone are insufficient. No local source was uploaded and no remote code was executed.}]]
    }
XQL Not present:
Generic, PostgreSQL, Oracle
[ hide source ] | [ make this the default ]
Show another procedure: