chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:44:08 +08:00
commit 983960e2dd
1244 changed files with 281996 additions and 0 deletions
@@ -0,0 +1 @@
{}
@@ -0,0 +1,444 @@
import fs from 'node:fs'
import path from 'node:path'
import {
CODEBASE_CONTEXT_PATH,
PROFILE_CONTEXT_PATH
} from '@bridge/constants'
import { Tool } from '@sdk/base-tool'
import { ToolkitConfig } from '@sdk/toolkit-config'
const DEFAULT_LIST_LIMIT = 24
const DEFAULT_TOP_K = 8
const DEFAULT_SNIPPET_CHARS = Number.MAX_SAFE_INTEGER
const CODEBASE_CONTEXT_FILES = new Set([
'ARCHITECTURE.md',
'LEON.md'
])
interface ContextListEntry {
filename: string
summary: string
sizeChars: number
updatedAt: string
}
interface SearchHit {
filename: string
score: number
snippet: string
matchIndex: number
}
export default class ContextTool extends Tool {
private static readonly TOOLKIT = 'structured_knowledge'
private readonly config: ReturnType<typeof ToolkitConfig.load>
constructor() {
super()
this.config = ToolkitConfig.load(ContextTool.TOOLKIT, this.toolName)
this.settings = ToolkitConfig.loadToolSettings(
ContextTool.TOOLKIT,
this.toolName,
{}
)
this.requiredSettings = []
this.checkRequiredSettings(this.toolName)
}
get toolName(): string {
return 'context'
}
get toolkit(): string {
return ContextTool.TOOLKIT
}
get description(): string {
return this.config['description']
}
public async listContextFiles(
query = '',
limit = DEFAULT_LIST_LIMIT
): Promise<{
success: boolean
data: {
total: number
files: ContextListEntry[]
}
}> {
await this.ensureContextDir()
const files = await this.readContextEntries()
const normalizedQuery = String(query || '').trim().toLowerCase()
const maxItems = this.clampNumber(limit, 1, 100, DEFAULT_LIST_LIMIT)
const filtered = normalizedQuery
? files.filter((entry) => {
const target = `${entry.filename}\n${entry.summary}`.toLowerCase()
return target.includes(normalizedQuery)
})
: files
return {
success: true,
data: {
total: filtered.length,
files: filtered.slice(0, maxItems)
}
}
}
public async readContextFile(
filename: string,
options: { offsetChars?: number, maxChars?: number } = {}
): Promise<{
success: boolean
data?: {
filename: string
offsetChars: number
maxChars: number
returnedChars: number
totalChars: number
hasMore: boolean
nextOffsetChars: number | null
content: string
fullyShared: boolean
}
error?: string
}> {
const safeFilename = this.resolveFilename(filename)
if (!safeFilename) {
return {
success: false,
error: 'Invalid context filename.'
}
}
const filePath = this.resolveContextFilePath(safeFilename)
if (!fs.existsSync(filePath)) {
return {
success: false,
error: `Context file not found: ${safeFilename}`
}
}
const content = await fs.promises.readFile(filePath, 'utf8')
const totalChars = content.length
const offsetChars = this.clampNumber(
options.offsetChars,
0,
totalChars,
0
)
const remainingChars = Math.max(0, totalChars - offsetChars)
const requestedMaxChars = Number(options.maxChars)
const maxChars =
totalChars > 0 &&
Number.isFinite(requestedMaxChars) &&
requestedMaxChars > 0
? this.clampNumber(requestedMaxChars, 1, totalChars, totalChars)
: remainingChars
const chunk = content.slice(offsetChars, offsetChars + maxChars)
const nextOffset = offsetChars + chunk.length
const hasMore = nextOffset < totalChars
return {
success: true,
data: {
filename: safeFilename,
offsetChars,
maxChars,
returnedChars: chunk.length,
totalChars,
hasMore,
nextOffsetChars: hasMore ? nextOffset : null,
content: chunk,
fullyShared: !hasMore && offsetChars === 0
}
}
}
public async searchContext(
query: string,
options: {
filenames?: string[]
topK?: number
snippetChars?: number
} = {}
): Promise<{
success: boolean
data: {
query: string
topK: number
searchedFiles: string[]
hits: SearchHit[]
}
}> {
await this.ensureContextDir()
const normalizedQuery = String(query || '').trim()
if (!normalizedQuery) {
return {
success: true,
data: {
query: '',
topK: 0,
searchedFiles: [],
hits: []
}
}
}
const entries = await this.readContextEntries()
const allowed = new Set(
(options.filenames || [])
.map((filename) => this.resolveFilename(filename))
.filter((filename): filename is string => Boolean(filename))
)
const topK = this.clampNumber(options.topK, 1, 24, DEFAULT_TOP_K)
const requestedSnippetChars = Number(options.snippetChars)
const snippetChars =
Number.isFinite(requestedSnippetChars) && requestedSnippetChars > 0
? Math.floor(requestedSnippetChars)
: DEFAULT_SNIPPET_CHARS
const searchableEntries =
allowed.size > 0
? entries.filter((entry) => allowed.has(entry.filename))
: entries
const queryTokens = this.tokenize(normalizedQuery)
const hits: SearchHit[] = []
for (const entry of searchableEntries) {
const lower = entry.content.toLowerCase()
const tokenScores = queryTokens.map((token) => {
if (!token) {
return 0
}
return lower.includes(token) ? 1 : 0
})
const tokenMatchCount = tokenScores.reduce<number>(
(total, score) => total + score,
0
)
if (tokenMatchCount === 0) {
continue
}
const fullQueryIndex = lower.indexOf(normalizedQuery.toLowerCase())
const fallbackIndex =
fullQueryIndex >= 0
? fullQueryIndex
: queryTokens.reduce((best, token) => {
if (!token) {
return best
}
const idx = lower.indexOf(token)
if (idx === -1) {
return best
}
if (best === -1) {
return idx
}
return Math.min(best, idx)
}, -1)
const matchIndex = Math.max(0, fallbackIndex)
const score =
tokenMatchCount / Math.max(1, queryTokens.length) +
(fullQueryIndex >= 0 ? 0.5 : 0)
hits.push({
filename: entry.filename,
score,
snippet: this.buildSnippet(entry.content, matchIndex, snippetChars),
matchIndex
})
}
hits.sort((a, b) => {
if (a.score !== b.score) {
return b.score - a.score
}
return a.matchIndex - b.matchIndex
})
return {
success: true,
data: {
query: normalizedQuery,
topK,
searchedFiles: searchableEntries.map((entry) => entry.filename),
hits: hits.slice(0, topK)
}
}
}
private async ensureContextDir(): Promise<void> {
await fs.promises.mkdir(PROFILE_CONTEXT_PATH, { recursive: true })
}
private resolveFilename(filename: string): string | null {
const normalized = path.basename(String(filename || '').trim())
if (!normalized || !normalized.toUpperCase().endsWith('.MD')) {
return null
}
if (!this.isSafeContextFilename(normalized)) {
return null
}
return normalized
}
private resolveContextFilePath(filename: string): string {
return path.join(this.getContextDirectory(filename), filename)
}
private getContextDirectory(filename: string): string {
if (CODEBASE_CONTEXT_FILES.has(filename)) {
return CODEBASE_CONTEXT_PATH
}
return PROFILE_CONTEXT_PATH
}
private isSafeContextFilename(filename: string): boolean {
return path.basename(filename) === filename
}
private async readContextEntries(): Promise<Array<{
filename: string
summary: string
sizeChars: number
updatedAt: string
content: string
}>> {
const markdownFiles = await this.listContextFilenames()
const output: Array<{
filename: string
summary: string
sizeChars: number
updatedAt: string
content: string
}> = []
for (const filename of markdownFiles) {
const filePath = this.resolveContextFilePath(filename)
const [stat, content] = await Promise.all([
fs.promises.stat(filePath),
fs.promises.readFile(filePath, 'utf8')
])
const summary = this.extractSummary(content)
output.push({
filename,
summary,
sizeChars: content.length,
updatedAt: stat.mtime.toISOString(),
content
})
}
return output
}
private async listContextFilenames(): Promise<string[]> {
const filenames = new Set<string>()
await this.addContextFilenamesFromDirectory(
CODEBASE_CONTEXT_PATH,
filenames,
(filename) => CODEBASE_CONTEXT_FILES.has(filename)
)
await this.addContextFilenamesFromDirectory(
PROFILE_CONTEXT_PATH,
filenames,
(filename) => !CODEBASE_CONTEXT_FILES.has(filename)
)
return [...filenames].sort((a, b) => a.localeCompare(b))
}
private async addContextFilenamesFromDirectory(
directoryPath: string,
filenames: Set<string>,
shouldInclude: (filename: string) => boolean
): Promise<void> {
let entries: fs.Dirent[] = []
try {
entries = await fs.promises.readdir(directoryPath, {
withFileTypes: true
})
} catch {
return
}
for (const entry of entries) {
if (
!entry.isFile() ||
!entry.name.toLowerCase().endsWith('.md') ||
!this.isSafeContextFilename(entry.name) ||
!shouldInclude(entry.name)
) {
continue
}
filenames.add(entry.name)
}
}
private extractSummary(content: string): string {
const lines = content
.split('\n')
.map((line) => line.trim())
.filter((line) => line.length > 0)
const preferred = lines.find((line) => line.startsWith('>'))
const first = preferred || lines[0] || ''
const normalized = first.replace(/^>\s*/, '').replace(/\s+/g, ' ').trim()
if (!normalized) {
return ''
}
return normalized.length > 180
? `${normalized.slice(0, 177).trimEnd()}...`
: normalized
}
private tokenize(value: string): string[] {
return (value.toLowerCase().match(/[a-z0-9_]+/g) || [])
.map((token) => token.trim())
.filter((token) => token.length >= 2)
}
private clampNumber(
value: unknown,
min: number,
max: number,
fallback: number
): number {
const parsed = Number(value)
if (!Number.isFinite(parsed)) {
return fallback
}
return Math.max(min, Math.min(max, Math.floor(parsed)))
}
private buildSnippet(content: string, center: number, maxChars: number): string {
if (content.length <= maxChars) {
return content
}
const half = Math.floor(maxChars / 2)
const start = Math.max(0, center - half)
const end = Math.min(content.length, start + maxChars)
const raw = content.slice(start, end)
const prefix = start > 0 ? '...' : ''
const suffix = end < content.length ? '...' : ''
return `${prefix}${raw}${suffix}`
}
}
@@ -0,0 +1 @@
export { default } from './context-tool'
@@ -0,0 +1,108 @@
{
"$schema": "../../../schemas/tool-schemas/tool.json",
"tool_id": "context",
"toolkit_id": "structured_knowledge",
"name": "Context",
"description": "Read and search Leon context files.",
"icon_name": "file-list-3-line",
"author": {
"name": "Louis Grenard",
"email": "louis@getleon.ai",
"url": "https://twitter.com/grenlouis"
},
"functions": {
"listContextFiles": {
"description": "List available context files with short summaries.",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string"
},
"limit": {
"type": "number"
}
},
"additionalProperties": false
}
},
"readContextFile": {
"description": "Read a context file. By default, returns full file content.",
"parameters": {
"type": "object",
"properties": {
"filename": {
"type": "string",
"enum": [
"ACTIVITY.md",
"ARCHITECTURE.md",
"BROWSER_HISTORY.md",
"GPU_COMPUTE.md",
"HABITS.md",
"HOME.md",
"HOST_SYSTEM.md",
"LEON.md",
"LEON_RUNTIME.md",
"LOCAL_INVENTORY.md",
"MEDIA_PROFILE.md",
"NETWORK_ECOSYSTEM.md",
"OWNER.md",
"STORAGE.md",
"SYSTEM_RESOURCES.md",
"WORKSPACE_INTELLIGENCE.md"
]
},
"options": {
"type": "object",
"properties": {
"offsetChars": {
"type": "number"
},
"maxChars": {
"type": "number"
}
},
"additionalProperties": false
}
},
"required": [
"filename"
],
"additionalProperties": false
}
},
"searchContext": {
"description": "Search relevant content across context files.",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string"
},
"options": {
"type": "object",
"properties": {
"filenames": {
"type": "array",
"items": {
"type": "string"
}
},
"topK": {
"type": "number"
},
"snippetChars": {
"type": "number"
}
},
"additionalProperties": false
}
},
"required": [
"query"
],
"additionalProperties": false
}
}
}
}
@@ -0,0 +1 @@
{}
@@ -0,0 +1 @@
export { default } from './memory-tool'
File diff suppressed because it is too large Load Diff
+125
View File
@@ -0,0 +1,125 @@
{
"$schema": "../../../schemas/tool-schemas/tool.json",
"tool_id": "memory",
"toolkit_id": "structured_knowledge",
"name": "Memory",
"description": "Read and write Leon memory entries (persistent, daily, discussion).",
"icon_name": "brain-2-line",
"author": {
"name": "Louis Grenard",
"email": "louis@getleon.ai",
"url": "https://twitter.com/grenlouis"
},
"functions": {
"read": {
"description": "Recall relevant memories for a query using Leon's memory system. Keep the query short and semantically close to the user's wording. Prefer concrete entities or relationships already mentioned. Avoid long speculative keyword lists.",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string"
},
"options": {
"type": "object",
"properties": {
"namespaces": {
"type": "array",
"items": {
"type": "string",
"enum": [
"memory_persistent",
"memory_daily",
"memory_discussion",
"conversation_daily",
"context"
]
}
},
"topK": {
"type": "number"
},
"tokenBudget": {
"type": "number"
},
"includeFacts": {
"type": "boolean"
},
"includeContext": {
"type": "boolean"
},
"contextFilenames": {
"type": "array",
"items": {
"type": "string"
}
}
},
"additionalProperties": false
}
},
"required": [
"query"
]
}
},
"write": {
"description": "Write a memory item into Leon memory (persistent/daily/discussion).",
"parameters": {
"type": "object",
"properties": {
"content": {
"type": "string"
},
"options": {
"type": "object",
"properties": {
"scope": {
"type": "string"
},
"kind": {
"type": "string"
},
"title": {
"type": "string"
},
"sourceType": {
"type": "string"
},
"sourceRef": {
"type": "string"
},
"importance": {
"type": "number"
},
"confidence": {
"type": "number"
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"dayKey": {
"type": "string"
},
"expiresAt": {
"type": "number"
},
"isPinned": {
"type": "boolean"
},
"metadata": {
"type": "object"
}
},
"additionalProperties": false
}
},
"required": [
"content"
]
}
}
}
}
+14
View File
@@ -0,0 +1,14 @@
{
"$schema": "../../schemas/toolkit-schemas/toolkit.json",
"name": "Structured Knowledge",
"description": "Tools for structured knowledge and facts.",
"icon_name": "database-2-line",
"context_files": [
"LEON.md",
"ARCHITECTURE.md"
],
"tools": [
"memory",
"context"
]
}