diff --git a/Cargo.lock b/Cargo.lock index 950ff92..71f1971 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2094,7 +2094,7 @@ dependencies = [ [[package]] name = "memory-sync-gui" -version = "2026.10328.106" +version = "2026.10329.110" dependencies = [ "dirs", "proptest", @@ -4372,7 +4372,7 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tnmsc" -version = "2026.10328.106" +version = "2026.10329.110" dependencies = [ "clap", "dirs", @@ -4394,7 +4394,7 @@ dependencies = [ [[package]] name = "tnmsc-logger" -version = "2026.10328.106" +version = "2026.10329.110" dependencies = [ "chrono", "napi", @@ -4406,7 +4406,7 @@ dependencies = [ [[package]] name = "tnmsc-md-compiler" -version = "2026.10328.106" +version = "2026.10329.110" dependencies = [ "markdown", "napi", @@ -4421,7 +4421,7 @@ dependencies = [ [[package]] name = "tnmsc-script-runtime" -version = "2026.10328.106" +version = "2026.10329.110" dependencies = [ "napi", "napi-build", diff --git a/Cargo.toml b/Cargo.toml index 450ac3e..f44a85d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ members = [ ] [workspace.package] -version = "2026.10328.106" +version = "2026.10329.110" edition = "2024" license = "AGPL-3.0-only" authors = ["TrueNine"] diff --git a/cli/npm/darwin-arm64/package.json b/cli/npm/darwin-arm64/package.json index d6e039e..c6be197 100644 --- a/cli/npm/darwin-arm64/package.json +++ b/cli/npm/darwin-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-cli-darwin-arm64", - "version": "2026.10328.106", + "version": "2026.10329.110", "os": [ "darwin" ], diff --git a/cli/npm/darwin-x64/package.json b/cli/npm/darwin-x64/package.json index f6a14ee..96f2661 100644 --- a/cli/npm/darwin-x64/package.json +++ b/cli/npm/darwin-x64/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-cli-darwin-x64", - "version": "2026.10328.106", + "version": "2026.10329.110", "os": [ "darwin" ], diff --git a/cli/npm/linux-arm64-gnu/package.json b/cli/npm/linux-arm64-gnu/package.json index f968973..1a16a29 100644 --- a/cli/npm/linux-arm64-gnu/package.json +++ b/cli/npm/linux-arm64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-cli-linux-arm64-gnu", - "version": "2026.10328.106", + "version": "2026.10329.110", "os": [ "linux" ], diff --git a/cli/npm/linux-x64-gnu/package.json b/cli/npm/linux-x64-gnu/package.json index 9087741..faf1796 100644 --- a/cli/npm/linux-x64-gnu/package.json +++ b/cli/npm/linux-x64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-cli-linux-x64-gnu", - "version": "2026.10328.106", + "version": "2026.10329.110", "os": [ "linux" ], diff --git a/cli/npm/win32-x64-msvc/package.json b/cli/npm/win32-x64-msvc/package.json index 6a8f34b..1799e80 100644 --- a/cli/npm/win32-x64-msvc/package.json +++ b/cli/npm/win32-x64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-cli-win32-x64-msvc", - "version": "2026.10328.106", + "version": "2026.10329.110", "os": [ "win32" ], diff --git a/cli/package.json b/cli/package.json index c063b83..8223fa9 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,7 +1,7 @@ { "name": "@truenine/memory-sync-cli", "type": "module", - "version": "2026.10328.106", + "version": "2026.10329.110", "description": "TrueNine Memory Synchronization CLI", "author": "TrueNine", "license": "AGPL-3.0-only", @@ -51,18 +51,23 @@ "build": "run-s build:deps build:napi bundle finalize:bundle generate:schema", "build:napi": "tsx ../scripts/copy-napi.ts", "build:deps": "pnpm -F @truenine/logger -F @truenine/md-compiler -F @truenine/script-runtime run build", + "build:deps:ts": "pnpm -F @truenine/logger -F @truenine/md-compiler -F @truenine/script-runtime run build:ts", "bundle": "tsx ../scripts/build-quiet.ts", - "check": "run-p typecheck lint", + "check": "run-s build:deps:ts check:run", + "check:run": "run-p lint:run typecheck:run", "finalize:bundle": "tsx scripts/finalize-bundle.ts", "generate:schema": "tsx scripts/generate-schema.ts", - "lint": "eslint --cache --cache-location node_modules/.cache/.eslintcache .", + "lint": "run-s build:deps:ts lint:run", + "lint:run": "eslint --cache --cache-location node_modules/.cache/.eslintcache .", "prepublishOnly": "run-s build check", "test": "run-s build:deps test:run", "test:native-cleanup-smoke": "tsx scripts/cleanup-native-smoke.ts", "test:run": "vitest run", "benchmark:cleanup": "tsx scripts/benchmark-cleanup.ts", - "lintfix": "eslint --fix --cache --cache-location node_modules/.cache/.eslintcache .", - "typecheck": "tsc --noEmit -p tsconfig.lib.json" + "lintfix": "run-s build:deps:ts lintfix:run", + "lintfix:run": "eslint --fix --cache --cache-location node_modules/.cache/.eslintcache .", + "typecheck": "run-s build:deps:ts typecheck:run", + "typecheck:run": "tsc --noEmit -p tsconfig.lib.json" }, "dependencies": { "json5": "catalog:", diff --git a/cli/src/ConfigLoader.test.ts b/cli/src/ConfigLoader.test.ts index e13681e..7a72fc1 100644 --- a/cli/src/ConfigLoader.test.ts +++ b/cli/src/ConfigLoader.test.ts @@ -32,4 +32,36 @@ describe('configLoader', () => { fs.rmSync(tempHome, {recursive: true, force: true}) } }) + + it('defaults aindex.softwares when loading an older config file', () => { + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'tnmsc-config-loader-')) + const configPath = path.join(tempDir, '.tnmsc.json') + + try { + fs.writeFileSync(configPath, JSON.stringify({ + workspaceDir: '/tmp/workspace', + aindex: { + dir: 'aindex', + skills: {src: 'skills', dist: 'dist/skills'}, + commands: {src: 'commands', dist: 'dist/commands'}, + subAgents: {src: 'subagents', dist: 'dist/subagents'}, + rules: {src: 'rules', dist: 'dist/rules'}, + globalPrompt: {src: 'global.src.mdx', dist: 'dist/global.mdx'}, + workspacePrompt: {src: 'workspace.src.mdx', dist: 'dist/workspace.mdx'}, + app: {src: 'app', dist: 'dist/app'}, + ext: {src: 'ext', dist: 'dist/ext'}, + arch: {src: 'arch', dist: 'dist/arch'} + } + }), 'utf8') + + const loader = new ConfigLoader() + const result = loader.loadFromFile(configPath) + + expect(result.found).toBe(true) + expect(result.config.aindex?.softwares).toEqual({src: 'softwares', dist: 'dist/softwares'}) + } + finally { + fs.rmSync(tempDir, {recursive: true, force: true}) + } + }) }) diff --git a/cli/src/ConfigLoader.ts b/cli/src/ConfigLoader.ts index fbb1a9f..90e15cf 100644 --- a/cli/src/ConfigLoader.ts +++ b/cli/src/ConfigLoader.ts @@ -1,10 +1,10 @@ +import type {ILogger} from '@truenine/logger' import type { AindexConfig, CleanupProtectionOptions, ConfigLoaderOptions, ConfigLoadResult, FrontMatterOptions, - ILogger, OutputScopeOptions, PluginOutputScopeTopics, UserConfigFile, @@ -12,13 +12,14 @@ import type { } from './plugins/plugin-core' import * as fs from 'node:fs' import process from 'node:process' +import {createLogger} from '@truenine/logger' import { buildConfigDiagnostic, buildFileOperationDiagnostic, diagnosticLines, splitDiagnosticText } from './diagnostics' -import {createLogger, ZUserConfigFile} from './plugins/plugin-core' +import {mergeAindexConfig, ZUserConfigFile} from './plugins/plugin-core' import { getRequiredGlobalConfigPath, resolveRuntimeEnvironment, @@ -189,18 +190,7 @@ export class ConfigLoader { if (a == null && b == null) return void 0 if (a == null) return b if (b == null) return a - return { - dir: b.dir ?? a.dir, - skills: {...a.skills, ...b.skills}, - commands: {...a.commands, ...b.commands}, - subAgents: {...a.subAgents, ...b.subAgents}, - rules: {...a.rules, ...b.rules}, - globalPrompt: {...a.globalPrompt, ...b.globalPrompt}, - workspacePrompt: {...a.workspacePrompt, ...b.workspacePrompt}, - app: {...a.app, ...b.app}, - ext: {...a.ext, ...b.ext}, - arch: {...a.arch, ...b.arch} - } + return mergeAindexConfig(a, b) } private mergeOutputScopeTopics( diff --git a/cli/src/ProtectedDeletionGuard.ts b/cli/src/ProtectedDeletionGuard.ts index b79926e..f064467 100644 --- a/cli/src/ProtectedDeletionGuard.ts +++ b/cli/src/ProtectedDeletionGuard.ts @@ -1,10 +1,15 @@ -import type {ILogger, OutputCollectedContext, PluginOptions} from './plugins/plugin-core' +import type {ILogger} from '@truenine/logger' +import type {OutputCollectedContext, PluginOptions} from './plugins/plugin-core' import type {PublicDefinitionResolveOptions} from './public-config-paths' import * as fs from 'node:fs' import * as path from 'node:path' import process from 'node:process' import glob from 'fast-glob' import {buildProtectedDeletionDiagnostic} from './diagnostics' +import { + AINDEX_CONFIG_DIRECTORY_PAIR_KEYS, + AINDEX_PROJECT_SERIES_NAMES +} from './plugins/plugin-core' import {collectKnownPublicConfigDefinitionPaths} from './public-config-paths' import {getEffectiveHomeDir, resolveUserPath} from './runtime-environment' @@ -70,16 +75,6 @@ export class ProtectedDeletionGuardError extends Error { } } -const CONFIGURED_AINDEX_DIRECTORY_KEYS = [ - 'skills', - 'commands', - 'subAgents', - 'rules', - 'app', - 'ext', - 'arch' -] as const satisfies readonly (keyof Required['aindex'])[] - const CONFIGURED_AINDEX_FILE_KEYS = [ 'globalPrompt', 'workspacePrompt' @@ -291,7 +286,7 @@ function collectWorkspaceReservedRules( 'workspace-reserved', 'glob' )) - for (const seriesName of ['app', 'ext', 'arch'] as const) { + for (const seriesName of AINDEX_PROJECT_SERIES_NAMES) { rules.push(createProtectedPathRule( path.join(workspaceDir, 'aindex', seriesName, '**', '*.mdx'), 'direct', @@ -321,10 +316,13 @@ export function collectConfiguredAindexInputRules( ): ProtectedPathRule[] { const rules: ProtectedPathRule[] = [] - for (const key of CONFIGURED_AINDEX_DIRECTORY_KEYS) { + for (const key of AINDEX_CONFIG_DIRECTORY_PAIR_KEYS) { + const configuredDir = pluginOptions.aindex[key] + if (configuredDir == null) continue + rules.push( createProtectedPathRule( - path.join(aindexDir, pluginOptions.aindex[key].src), + path.join(aindexDir, configuredDir.src), 'recursive', `configured aindex ${key} source directory`, 'configured-aindex-source' @@ -333,9 +331,12 @@ export function collectConfiguredAindexInputRules( } for (const key of CONFIGURED_AINDEX_FILE_KEYS) { + const configuredFile = pluginOptions.aindex[key] + if (configuredFile == null) continue + rules.push( createProtectedPathRule( - path.join(aindexDir, pluginOptions.aindex[key].src), + path.join(aindexDir, configuredFile.src), 'direct', `configured aindex ${key} source file`, 'configured-aindex-source' diff --git a/cli/src/commands/Command.ts b/cli/src/commands/Command.ts index fe512ce..7f83bc0 100644 --- a/cli/src/commands/Command.ts +++ b/cli/src/commands/Command.ts @@ -1,4 +1,12 @@ -import type {ILogger, LoggerDiagnosticRecord, OutputCleanContext, OutputCollectedContext, OutputPlugin, OutputWriteContext, PluginOptions, UserConfigFile} from '../plugins/plugin-core' +import type {ILogger, LoggerDiagnosticRecord} from '@truenine/logger' +import type { + OutputCleanContext, + OutputCollectedContext, + OutputPlugin, + OutputWriteContext, + PluginOptions, + UserConfigFile +} from '../plugins/plugin-core' /** * Command execution context diff --git a/cli/src/commands/ConfigCommand.ts b/cli/src/commands/ConfigCommand.ts index 3ac6f24..68b1027 100644 --- a/cli/src/commands/ConfigCommand.ts +++ b/cli/src/commands/ConfigCommand.ts @@ -1,37 +1,22 @@ import type {Command, CommandContext, CommandResult} from './Command' +import type {AindexConfigKeyPath} from '@/plugins/plugin-core' import * as fs from 'node:fs' import * as path from 'node:path' import {buildUsageDiagnostic, diagnosticLines} from '@/diagnostics' +import {AINDEX_CONFIG_KEY_PATHS} from '@/plugins/plugin-core' import {getRequiredGlobalConfigPath} from '@/runtime-environment' /** * Valid configuration keys that can be set via `tnmsc config key=value`. * Nested keys use dot-notation: aindex.skills.src, aindex.commands.src, etc. */ -const VALID_CONFIG_KEYS = [ +type ValidConfigKey = 'workspaceDir' | 'logLevel' | AindexConfigKeyPath + +const VALID_CONFIG_KEYS: readonly ValidConfigKey[] = [ 'workspaceDir', - 'aindex.skills.src', - 'aindex.skills.dist', - 'aindex.commands.src', - 'aindex.commands.dist', - 'aindex.subAgents.src', - 'aindex.subAgents.dist', - 'aindex.rules.src', - 'aindex.rules.dist', - 'aindex.globalPrompt.src', - 'aindex.globalPrompt.dist', - 'aindex.workspacePrompt.src', - 'aindex.workspacePrompt.dist', - 'aindex.app.src', - 'aindex.app.dist', - 'aindex.ext.src', - 'aindex.ext.dist', - 'aindex.arch.src', - 'aindex.arch.dist', + ...AINDEX_CONFIG_KEY_PATHS, 'logLevel' -] as const - -type ValidConfigKey = typeof VALID_CONFIG_KEYS[number] +] /** * Validate if a key is a valid config key diff --git a/cli/src/commands/HelpCommand.ts b/cli/src/commands/HelpCommand.ts index 285b72b..ae7201d 100644 --- a/cli/src/commands/HelpCommand.ts +++ b/cli/src/commands/HelpCommand.ts @@ -1,7 +1,9 @@ import type {Command, CommandContext, CommandResult} from './Command' +import {AINDEX_CONFIG_KEY_PATHS} from '@/plugins/plugin-core' import {getCliVersion} from './VersionCommand' const CLI_NAME = 'tnmsc' +const CONFIG_KEY_LIST_TEXT = ['workspaceDir', 'logLevel', ...AINDEX_CONFIG_KEY_PATHS].join(',\n ') const HELP_TEXT = ` ${CLI_NAME} v${getCliVersion()} - Memory Sync CLI @@ -44,16 +46,7 @@ CLEAN OPTIONS: CONFIG OPTIONS: key=value Set a configuration value in global config (~/.aindex/.tnmsc.json) - Valid keys: workspaceDir, logLevel, - aindex.skills.src, aindex.skills.dist, - aindex.commands.src, aindex.commands.dist, - aindex.subAgents.src, aindex.subAgents.dist, - aindex.rules.src, aindex.rules.dist, - aindex.globalPrompt.src, aindex.globalPrompt.dist, - aindex.workspacePrompt.src, aindex.workspacePrompt.dist, - aindex.app.src, aindex.app.dist, - aindex.ext.src, aindex.ext.dist, - aindex.arch.src, aindex.arch.dist + Valid keys: ${CONFIG_KEY_LIST_TEXT} Examples: ${CLI_NAME} config workspaceDir=~/my-project diff --git a/cli/src/commands/ProtectedDeletionCommands.test.ts b/cli/src/commands/ProtectedDeletionCommands.test.ts index 9baa9fe..4904db2 100644 --- a/cli/src/commands/ProtectedDeletionCommands.test.ts +++ b/cli/src/commands/ProtectedDeletionCommands.test.ts @@ -4,6 +4,7 @@ import * as fs from 'node:fs' import * as path from 'node:path' import glob from 'fast-glob' import {describe, expect, it, vi} from 'vitest' +import {mergeConfig} from '../config' import {createLogger, FilePathKind, PluginKind} from '../plugins/plugin-core' import {CleanCommand} from './CleanCommand' import {DryRunCleanCommand} from './DryRunCleanCommand' @@ -49,6 +50,7 @@ function createCommandContext( workspaceDir: string = path.resolve('tmp-workspace-command') ): CommandContext { const aindexDir = path.join(workspaceDir, 'aindex') + const userConfigOptions = mergeConfig({workspaceDir}) const collectedOutputContext = { workspace: { directory: { @@ -74,54 +76,14 @@ function createCommandContext( logger: createMockLogger(), outputPlugins, collectedOutputContext, - userConfigOptions: { - version: '0.0.0', - workspaceDir, - logLevel: 'info', - aindex: { - dir: 'aindex', - skills: {src: 'skills', dist: 'dist/skills'}, - commands: {src: 'commands', dist: 'dist/commands'}, - subAgents: {src: 'subagents', dist: 'dist/subagents'}, - rules: {src: 'rules', dist: 'dist/rules'}, - globalPrompt: {src: 'global.src.mdx', dist: 'dist/global.mdx'}, - workspacePrompt: {src: 'workspace.src.mdx', dist: 'dist/workspace.mdx'}, - app: {src: 'app', dist: 'dist/app'}, - ext: {src: 'ext', dist: 'dist/ext'}, - arch: {src: 'arch', dist: 'dist/arch'} - }, - commandSeriesOptions: {}, - outputScopes: {}, - cleanupProtection: {}, - plugins: [] - }, + userConfigOptions, createCleanContext: (dryRun: boolean): OutputCleanContext => ({ logger: createMockLogger(), fs, path, glob, collectedOutputContext, - pluginOptions: { - version: '0.0.0', - workspaceDir, - logLevel: 'info', - aindex: { - dir: 'aindex', - skills: {src: 'skills', dist: 'dist/skills'}, - commands: {src: 'commands', dist: 'dist/commands'}, - subAgents: {src: 'subagents', dist: 'dist/subagents'}, - rules: {src: 'rules', dist: 'dist/rules'}, - globalPrompt: {src: 'global.src.mdx', dist: 'dist/global.mdx'}, - workspacePrompt: {src: 'workspace.src.mdx', dist: 'dist/workspace.mdx'}, - app: {src: 'app', dist: 'dist/app'}, - ext: {src: 'ext', dist: 'dist/ext'}, - arch: {src: 'arch', dist: 'dist/arch'} - }, - commandSeriesOptions: {}, - outputScopes: {}, - cleanupProtection: {}, - plugins: [] - }, + pluginOptions: userConfigOptions, dryRun }), createWriteContext: (dryRun: boolean): OutputWriteContext => ({ diff --git a/cli/src/config.test.ts b/cli/src/config.test.ts index 0971dc3..2b94ef4 100644 --- a/cli/src/config.test.ts +++ b/cli/src/config.test.ts @@ -44,7 +44,8 @@ describe('defineConfig', () => { workspacePrompt: {src: 'workspace.src.mdx', dist: 'dist/workspace.mdx'}, app: {src: 'app', dist: 'dist/app'}, ext: {src: 'ext', dist: 'dist/ext'}, - arch: {src: 'arch', dist: 'dist/arch'} + arch: {src: 'arch', dist: 'dist/arch'}, + softwares: {src: 'softwares', dist: 'dist/softwares'} }, logLevel: 'info' }), 'utf8') @@ -54,6 +55,7 @@ describe('defineConfig', () => { const result = await defineConfig({cwd: tempWorkspace}) expect(result.userConfigOptions.workspaceDir).toBe(tempWorkspace) + expect(result.userConfigOptions.aindex.softwares).toEqual({src: 'softwares', dist: 'dist/softwares'}) expect(result.context.workspace.directory.path).toBe(tempWorkspace) expect(result.context.aindexDir).toBe(path.join(tempWorkspace, 'aindex')) } diff --git a/cli/src/config.ts b/cli/src/config.ts index fb6a8ec..eff2e69 100644 --- a/cli/src/config.ts +++ b/cli/src/config.ts @@ -20,7 +20,9 @@ import {checkVersionControl} from './Aindex' import {getConfigLoader} from './ConfigLoader' import {collectInputContext, resolveRuntimeCommand} from './inputs/runtime' import { + buildDefaultAindexConfig, FilePathKind, + mergeAindexConfig, PathPlaceholders, toOutputCollectedContext, validateOutputScopeOverridesForPlugins @@ -51,18 +53,7 @@ function isInputCapability(plugin: InputCapability | OutputPlugin): plugin is In return 'collect' in plugin && !isOutputPlugin(plugin) } -const DEFAULT_AINDEX: Required = { - dir: 'aindex', - skills: {src: 'skills', dist: 'dist/skills'}, - commands: {src: 'commands', dist: 'dist/commands'}, - subAgents: {src: 'subagents', dist: 'dist/subagents'}, - rules: {src: 'rules', dist: 'dist/rules'}, - globalPrompt: {src: 'global.src.mdx', dist: 'dist/global.mdx'}, - workspacePrompt: {src: 'workspace.src.mdx', dist: 'dist/workspace.mdx'}, - app: {src: 'app', dist: 'dist/app'}, - ext: {src: 'ext', dist: 'dist/ext'}, - arch: {src: 'arch', dist: 'dist/arch'} -} +const DEFAULT_AINDEX: Required = buildDefaultAindexConfig() const DEFAULT_OPTIONS: Required = { version: '0.0.0', @@ -141,7 +132,7 @@ function mergeTwoConfigs( return { ...base, ...override, - aindex: mergeAindex(base.aindex, override.aindex), + aindex: mergeAindexConfig(base.aindex, override.aindex), plugins: [ // Array concatenation for plugins ...base.plugins, ...overridePlugins ?? [] @@ -154,25 +145,6 @@ function mergeTwoConfigs( } } -function mergeAindex( - base: AindexConfig, - override?: AindexConfig -): AindexConfig { - if (override == null) return base - return { - dir: override.dir ?? base.dir, - skills: {...base.skills, ...override.skills}, - commands: {...base.commands, ...override.commands}, - subAgents: {...base.subAgents, ...override.subAgents}, - rules: {...base.rules, ...override.rules}, - globalPrompt: {...base.globalPrompt, ...override.globalPrompt}, - workspacePrompt: {...base.workspacePrompt, ...override.workspacePrompt}, - app: {...base.app, ...override.app}, - ext: {...base.ext, ...override.ext}, - arch: {...base.arch, ...override.arch} - } -} - function mergeCommandSeriesOptions( base?: CommandSeriesOptions, override?: CommandSeriesOptions diff --git a/cli/src/core/cleanup.rs b/cli/src/core/cleanup.rs index 2279655..bbe3ec6 100644 --- a/cli/src/core/cleanup.rs +++ b/cli/src/core/cleanup.rs @@ -645,7 +645,7 @@ fn collect_workspace_reserved_rules( "workspace-reserved", Some(ProtectionRuleMatcherDto::Glob), )); - for series_name in ["app", "ext", "arch"] { + for series_name in ["app", "ext", "arch", "softwares"] { rules.push(create_protected_rule( &format!("{workspace_dir}/aindex/{series_name}/**/*.mdx"), ProtectionModeDto::Direct, diff --git a/cli/src/core/config/mod.rs b/cli/src/core/config/mod.rs index 19fe1a4..8ed0941 100644 --- a/cli/src/core/config/mod.rs +++ b/cli/src/core/config/mod.rs @@ -91,6 +91,8 @@ pub struct AindexConfig { pub ext: Option, #[serde(default, skip_serializing_if = "Option::is_none")] pub arch: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub softwares: Option, } /// Per-plugin fast command series override options. @@ -602,6 +604,7 @@ fn merge_aindex(a: &Option, b: &Option) -> Option { fs.rmSync(tempWorkspace, {recursive: true, force: true}) } }) + + it('cleans orphaned softwares dist files using the matching software source root', async () => { + const tempWorkspace = fs.mkdtempSync(path.join(os.tmpdir(), 'tnmsc-orphan-cleanup-softwares-')) + const softwareSrcFile = path.join(tempWorkspace, 'aindex', 'softwares', 'tool-a', 'agt.src.mdx') + const softwareDistFile = path.join(tempWorkspace, 'aindex', 'dist', 'softwares', 'tool-a', 'agt.mdx') + const orphanSoftwareDistFile = path.join(tempWorkspace, 'aindex', 'dist', 'softwares', 'tool-b', 'agt.mdx') + + try { + fs.mkdirSync(path.dirname(softwareSrcFile), {recursive: true}) + fs.mkdirSync(path.dirname(softwareDistFile), {recursive: true}) + fs.mkdirSync(path.dirname(orphanSoftwareDistFile), {recursive: true}) + fs.writeFileSync(softwareSrcFile, '---\ndescription: software\n---\nSoftware prompt', 'utf8') + fs.writeFileSync(softwareDistFile, 'Software dist', 'utf8') + fs.writeFileSync(orphanSoftwareDistFile, 'Orphan software dist', 'utf8') + + const plugin = new OrphanFileCleanupEffectInputCapability() + const [result] = await plugin.executeEffects(createContext(tempWorkspace)) + + expect(result?.success).toBe(true) + expect(fs.existsSync(softwareDistFile)).toBe(true) + expect(fs.existsSync(orphanSoftwareDistFile)).toBe(false) + expect(result?.deletedDirs ?? []).toContain(path.dirname(orphanSoftwareDistFile)) + expect(result?.deletedFiles ?? []).not.toContain(softwareDistFile) + } + finally { + fs.rmSync(tempWorkspace, {recursive: true, force: true}) + } + }) + + it('cleans orphaned subagent dist files using the configured subagents source root', async () => { + const tempWorkspace = fs.mkdtempSync(path.join(os.tmpdir(), 'tnmsc-orphan-cleanup-subagents-')) + const subAgentSrcFile = path.join(tempWorkspace, 'aindex', 'subagents', 'qa', 'boot.src.mdx') + const subAgentDistFile = path.join(tempWorkspace, 'aindex', 'dist', 'subagents', 'qa', 'boot.mdx') + const orphanSubAgentDistFile = path.join(tempWorkspace, 'aindex', 'dist', 'subagents', 'ops', 'boot.mdx') + + try { + fs.mkdirSync(path.dirname(subAgentSrcFile), {recursive: true}) + fs.mkdirSync(path.dirname(subAgentDistFile), {recursive: true}) + fs.mkdirSync(path.dirname(orphanSubAgentDistFile), {recursive: true}) + fs.writeFileSync(subAgentSrcFile, '---\ndescription: subagent\n---\nSubagent prompt', 'utf8') + fs.writeFileSync(subAgentDistFile, 'Subagent dist', 'utf8') + fs.writeFileSync(orphanSubAgentDistFile, 'Orphan subagent dist', 'utf8') + + const plugin = new OrphanFileCleanupEffectInputCapability() + const [result] = await plugin.executeEffects(createContext(tempWorkspace)) + + expect(result?.success).toBe(true) + expect(fs.existsSync(subAgentDistFile)).toBe(true) + expect(fs.existsSync(orphanSubAgentDistFile)).toBe(false) + expect(result?.deletedDirs ?? []).toContain(path.dirname(orphanSubAgentDistFile)) + expect(result?.deletedFiles ?? []).not.toContain(subAgentDistFile) + } + finally { + fs.rmSync(tempWorkspace, {recursive: true, force: true}) + } + }) }) diff --git a/cli/src/inputs/effect-orphan-cleanup.ts b/cli/src/inputs/effect-orphan-cleanup.ts index 4480e14..a0356d5 100644 --- a/cli/src/inputs/effect-orphan-cleanup.ts +++ b/cli/src/inputs/effect-orphan-cleanup.ts @@ -1,9 +1,19 @@ -import type {InputCapabilityContext, InputCollectedContext, InputEffectContext, InputEffectResult} from '../plugins/plugin-core' -import {resolveAindexProjectSeriesConfigs} from '@/aindex-project-series' +import type { + AindexPromptTreeDirectoryPairKey, + InputCapabilityContext, + InputCollectedContext, + InputEffectContext, + InputEffectResult, + PluginOptions +} from '../plugins/plugin-core' import {buildFileOperationDiagnostic} from '@/diagnostics' import {compactDeletionTargets} from '../cleanup/delete-targets' import {deleteTargets} from '../core/desk-paths' -import {AbstractInputCapability, SourcePromptFileExtensions} from '../plugins/plugin-core' +import { + AbstractInputCapability, + AINDEX_PROMPT_TREE_DIRECTORY_PAIR_KEYS, + SourcePromptFileExtensions +} from '../plugins/plugin-core' import { collectConfiguredAindexInputRules, createProtectedDeletionGuard, @@ -16,11 +26,11 @@ export interface OrphanCleanupEffectResult extends InputEffectResult { readonly deletedDirs: string[] } -const OrphanCleanupDistSubDirs = ['skills', 'commands', 'agents', 'app', 'ext', 'arch'] as const - -type OrphanCleanupSubDir = (typeof OrphanCleanupDistSubDirs)[number] - -type OrphanCleanupSourcePaths = Readonly> +interface OrphanCleanupDirectoryConfig { + readonly key: AindexPromptTreeDirectoryPairKey + readonly srcPath: string + readonly distPath: string +} interface OrphanCleanupPlan { readonly filesToDelete: string[] @@ -56,24 +66,31 @@ export class OrphanFileCleanupEffectInputCapability extends AbstractInputCapabil protected buildDeletionPlan( ctx: InputEffectContext, - distDir: string, - srcPaths: OrphanCleanupSourcePaths + directoryConfigs: readonly OrphanCleanupDirectoryConfig[] ): OrphanCleanupPlan { const filesToDelete: string[] = [] const dirsToDelete: string[] = [] const errors: {path: string, error: Error}[] = [] - for (const subDir of OrphanCleanupDistSubDirs) { - const distSubDirPath = ctx.path.join(distDir, subDir) + for (const directoryConfig of directoryConfigs) { + const distSubDirPath = ctx.path.join(ctx.aindexDir, directoryConfig.distPath) if (!ctx.fs.existsSync(distSubDirPath)) continue if (!ctx.fs.statSync(distSubDirPath).isDirectory()) continue - const subDirWillBeEmpty = this.collectDirectoryPlan(ctx, distSubDirPath, subDir, srcPaths[subDir], filesToDelete, dirsToDelete, errors) + const subDirWillBeEmpty = this.collectDirectoryPlan(ctx, distSubDirPath, directoryConfig, filesToDelete, dirsToDelete, errors) if (subDirWillBeEmpty) dirsToDelete.push(distSubDirPath) } return {filesToDelete, dirsToDelete, errors} } + protected resolveDirectoryConfigs(options: Required): readonly OrphanCleanupDirectoryConfig[] { + return AINDEX_PROMPT_TREE_DIRECTORY_PAIR_KEYS.map(key => ({ + key, + srcPath: options.aindex[key].src, + distPath: options.aindex[key].dist + })) + } + private async cleanupOrphanFiles(ctx: InputEffectContext): Promise { const {fs, path, aindexDir, logger, userConfigOptions, dryRun} = ctx const distDir = path.join(aindexDir, 'dist') @@ -88,18 +105,7 @@ export class OrphanFileCleanupEffectInputCapability extends AbstractInputCapabil } } - const aindexConfig = userConfigOptions.aindex - const projectSeries = resolveAindexProjectSeriesConfigs(userConfigOptions) - const srcPaths: OrphanCleanupSourcePaths = { - skills: aindexConfig?.skills?.src ?? 'skills', - commands: aindexConfig?.commands?.src ?? 'commands', - agents: aindexConfig?.subAgents?.src ?? 'subagents', - app: projectSeries.find(series => series.name === 'app')?.src ?? 'app', - ext: projectSeries.find(series => series.name === 'ext')?.src ?? 'ext', - arch: projectSeries.find(series => series.name === 'arch')?.src ?? 'arch' - } - - const plan = this.buildDeletionPlan(ctx, distDir, srcPaths) + const plan = this.buildDeletionPlan(ctx, this.resolveDirectoryConfigs(userConfigOptions)) const guard = this.buildProtectedDeletionGuard(ctx) const filePartition = partitionDeletionTargets(plan.filesToDelete, guard) @@ -182,8 +188,7 @@ export class OrphanFileCleanupEffectInputCapability extends AbstractInputCapabil protected collectDirectoryPlan( ctx: InputEffectContext, distDirPath: string, - dirType: string, - srcPath: string, + directoryConfig: OrphanCleanupDirectoryConfig, filesToDelete: string[], dirsToDelete: string[], errors: {path: string, error: Error}[] @@ -213,7 +218,14 @@ export class OrphanFileCleanupEffectInputCapability extends AbstractInputCapabil const entryPath = path.join(distDirPath, entry.name) if (entry.isDirectory()) { - const childWillBeEmpty = this.collectDirectoryPlan(ctx, entryPath, dirType, srcPath, filesToDelete, dirsToDelete, errors) + const childWillBeEmpty = this.collectDirectoryPlan( + ctx, + entryPath, + directoryConfig, + filesToDelete, + dirsToDelete, + errors + ) if (childWillBeEmpty) dirsToDelete.push(entryPath) else hasRetainedEntries = true continue @@ -224,7 +236,7 @@ export class OrphanFileCleanupEffectInputCapability extends AbstractInputCapabil continue } - const isOrphan = this.isOrphanFile(ctx, entryPath, dirType, srcPath, aindexDir) + const isOrphan = this.isOrphanFile(ctx, entryPath, directoryConfig, aindexDir) if (isOrphan) filesToDelete.push(entryPath) else hasRetainedEntries = true } @@ -235,8 +247,7 @@ export class OrphanFileCleanupEffectInputCapability extends AbstractInputCapabil private isOrphanFile( ctx: InputEffectContext, distFilePath: string, - dirType: string, - srcPath: string, + directoryConfig: OrphanCleanupDirectoryConfig, aindexDir: string ): boolean { const {fs, path} = ctx @@ -244,50 +255,50 @@ export class OrphanFileCleanupEffectInputCapability extends AbstractInputCapabil const fileName = path.basename(distFilePath) const isMdxFile = fileName.endsWith('.mdx') - const distTypeDir = path.join(aindexDir, 'dist', dirType) + const distTypeDir = path.join(aindexDir, directoryConfig.distPath) const relativeFromType = path.relative(distTypeDir, distFilePath) const relativeDir = path.dirname(relativeFromType) const baseName = fileName.replace(/\.mdx$/, '') - if (!isMdxFile) return !fs.existsSync(path.join(aindexDir, srcPath, relativeFromType)) + if (!isMdxFile) return !fs.existsSync(path.join(aindexDir, directoryConfig.srcPath, relativeFromType)) - const possibleSrcPaths = this.getPossibleSourcePaths(path, aindexDir, dirType, srcPath, baseName, relativeDir) + const possibleSrcPaths = this.getPossibleSourcePaths( + path, + aindexDir, + directoryConfig.key, + directoryConfig.srcPath, + baseName, + relativeDir + ) return !possibleSrcPaths.some(candidatePath => fs.existsSync(candidatePath)) } private getPossibleSourcePaths( nodePath: typeof import('node:path'), aindexDir: string, - dirType: string, + directoryKey: AindexPromptTreeDirectoryPairKey, srcPath: string, baseName: string, relativeDir: string ): string[] { - switch (dirType) { - case 'skills': { - const skillParts = relativeDir === '.' ? [baseName] : relativeDir.split(nodePath.sep) - const skillName = skillParts[0] ?? baseName - const remainingPath = relativeDir === '.' ? '' : relativeDir.slice(skillName.length + 1) - - if (remainingPath !== '') { - return SourcePromptFileExtensions.map(extension => nodePath.join(aindexDir, srcPath, skillName, remainingPath, `${baseName}${extension}`)) - } - - return [ - ...SourcePromptFileExtensions.map(extension => nodePath.join(aindexDir, srcPath, skillName, `SKILL${extension}`)), - ...SourcePromptFileExtensions.map(extension => nodePath.join(aindexDir, srcPath, skillName, `skill${extension}`)) - ] + if (directoryKey === 'skills') { + const skillParts = relativeDir === '.' ? [baseName] : relativeDir.split(nodePath.sep) + const skillName = skillParts[0] ?? baseName + const remainingPath = relativeDir === '.' ? '' : relativeDir.slice(skillName.length + 1) + + if (remainingPath !== '') { + return SourcePromptFileExtensions.map(extension => nodePath.join(aindexDir, srcPath, skillName, remainingPath, `${baseName}${extension}`)) } - case 'commands': - case 'agents': - case 'app': - case 'ext': - case 'arch': - return relativeDir === '.' - ? SourcePromptFileExtensions.map(extension => nodePath.join(aindexDir, srcPath, `${baseName}${extension}`)) - : SourcePromptFileExtensions.map(extension => nodePath.join(aindexDir, srcPath, relativeDir, `${baseName}${extension}`)) - default: return [] + + return [ + ...SourcePromptFileExtensions.map(extension => nodePath.join(aindexDir, srcPath, skillName, `SKILL${extension}`)), + ...SourcePromptFileExtensions.map(extension => nodePath.join(aindexDir, srcPath, skillName, `skill${extension}`)) + ] } + + return relativeDir === '.' + ? SourcePromptFileExtensions.map(extension => nodePath.join(aindexDir, srcPath, `${baseName}${extension}`)) + : SourcePromptFileExtensions.map(extension => nodePath.join(aindexDir, srcPath, relativeDir, `${baseName}${extension}`)) } collect(ctx: InputCapabilityContext): Partial { diff --git a/cli/src/inputs/input-aindex.test.ts b/cli/src/inputs/input-aindex.test.ts index 8185a65..38f41bf 100644 --- a/cli/src/inputs/input-aindex.test.ts +++ b/cli/src/inputs/input-aindex.test.ts @@ -46,7 +46,7 @@ function createContext( function createAindexProject( tempWorkspace: string, projectName: string, - series: 'app' | 'ext' | 'arch' = 'app' + series: 'app' | 'ext' | 'arch' | 'softwares' = 'app' ): { readonly configDir: string } { @@ -140,7 +140,7 @@ describe('aindex input capability project config loading', () => { } }) - it('collects app, ext, and arch projects with series-aware metadata', async () => { + it('collects app, ext, arch, and softwares projects with series-aware metadata', async () => { const tempWorkspace = fs.mkdtempSync(path.join(os.tmpdir(), 'tnmsc-aindex-project-series-')) const {logger} = createLoggerMock() @@ -148,6 +148,7 @@ describe('aindex input capability project config loading', () => { createAindexProject(tempWorkspace, 'project-a', 'app') createAindexProject(tempWorkspace, 'plugin-a', 'ext') createAindexProject(tempWorkspace, 'system-a', 'arch') + createAindexProject(tempWorkspace, 'tool-a', 'softwares') const result = await new AindexInputCapability().collect(createContext(tempWorkspace, logger)) const projects = result.workspace?.projects ?? [] @@ -155,7 +156,8 @@ describe('aindex input capability project config loading', () => { expect(projects.map(project => `${project.promptSeries}:${project.name}`)).toEqual([ 'app:project-a', 'ext:plugin-a', - 'arch:system-a' + 'arch:system-a', + 'softwares:tool-a' ]) } finally { @@ -163,13 +165,13 @@ describe('aindex input capability project config loading', () => { } }) - it('fails fast when app, ext, and arch reuse the same project name', async () => { + it('fails fast when app, ext, arch, and softwares reuse the same project name', async () => { const tempWorkspace = fs.mkdtempSync(path.join(os.tmpdir(), 'tnmsc-aindex-project-conflict-')) const {logger, error} = createLoggerMock() try { createAindexProject(tempWorkspace, 'project-a', 'app') - createAindexProject(tempWorkspace, 'project-a', 'ext') + createAindexProject(tempWorkspace, 'project-a', 'softwares') await expect(new AindexInputCapability().collect(createContext(tempWorkspace, logger))) .rejects diff --git a/cli/src/inputs/input-aindex.ts b/cli/src/inputs/input-aindex.ts index db9ed5a..048d721 100644 --- a/cli/src/inputs/input-aindex.ts +++ b/cli/src/inputs/input-aindex.ts @@ -178,13 +178,13 @@ export class AindexInputCapability extends AbstractInputCapability { logger.error(buildConfigDiagnostic({ code: AindexInputCapability.conflictingProjectSeriesCode, - title: 'Project names must be unique across app, ext, and arch', + title: 'Project names must be unique across app, ext, arch, and softwares', reason: diagnosticLines( - 'tnmsc maps project-scoped outputs back to workspace project names, so app/ext/arch cannot reuse the same directory name.', + 'tnmsc maps project-scoped outputs back to workspace project names, so app/ext/arch/softwares cannot reuse the same directory name.', `Conflicting project names: ${conflicts.map(conflict => conflict.projectName).join(', ')}` ), exactFix: diagnosticLines( - 'Rename the conflicting project directory in one of the app/ext/arch source trees and rerun tnmsc.' + 'Rename the conflicting project directory in one of the app/ext/arch/softwares source trees and rerun tnmsc.' ), possibleFixes: conflicts.map(conflict => diagnosticLines( `"${conflict.projectName}" is currently declared in: ${conflict.refs.map(ref => `${ref.seriesName} (${ref.seriesDir})`).join(', ')}` @@ -211,7 +211,7 @@ export class AindexInputCapability extends AbstractInputCapability { const projectSeries = resolveAindexProjectSeriesConfigs(options) // Project outputs intentionally collapse to /, so - // app/ext/arch must never reuse the same project directory name. + // app/ext/arch/softwares must never reuse the same project directory name. this.assertNoCrossSeriesProjectNameConflicts(ctx, aindexDir, projectSeries) const aindexProjects = await this.scanSeriesProjects(ctx, workspaceDir, aindexDir, aindexName, projectSeries) diff --git a/cli/src/inputs/input-project-prompt.test.ts b/cli/src/inputs/input-project-prompt.test.ts index 0c2e999..6a5dd8a 100644 --- a/cli/src/inputs/input-project-prompt.test.ts +++ b/cli/src/inputs/input-project-prompt.test.ts @@ -132,22 +132,27 @@ describe('project prompt input plugin workspace prompt support', () => { } }) - it('loads ext and arch project prompts using the same agt.mdx workflow as app', async () => { + it('loads ext, arch, and softwares project prompts using the same agt.mdx workflow as app', async () => { const tempWorkspace = fs.mkdtempSync(path.join(os.tmpdir(), 'tnmsc-project-prompt-series-')) const extRoot = path.join(tempWorkspace, 'aindex', 'dist', 'ext', 'plugin-a') const archRoot = path.join(tempWorkspace, 'aindex', 'dist', 'arch', 'system-a') + const softwareRoot = path.join(tempWorkspace, 'aindex', 'dist', 'softwares', 'tool-a') try { fs.mkdirSync(path.join(extRoot, 'docs'), {recursive: true}) fs.mkdirSync(path.join(archRoot, 'design'), {recursive: true}) + fs.mkdirSync(path.join(softwareRoot, 'manual'), {recursive: true}) fs.writeFileSync(path.join(extRoot, 'agt.mdx'), 'Ext root prompt', 'utf8') fs.writeFileSync(path.join(extRoot, 'docs', 'agt.mdx'), 'Ext child prompt', 'utf8') fs.writeFileSync(path.join(archRoot, 'agt.mdx'), 'Arch root prompt', 'utf8') fs.writeFileSync(path.join(archRoot, 'design', 'agt.mdx'), 'Arch child prompt', 'utf8') + fs.writeFileSync(path.join(softwareRoot, 'agt.mdx'), 'Software root prompt', 'utf8') + fs.writeFileSync(path.join(softwareRoot, 'manual', 'agt.mdx'), 'Software child prompt', 'utf8') const workspace = createWorkspace(tempWorkspace, [ createProject(tempWorkspace, 'plugin-a', {promptSeries: 'ext'}), - createProject(tempWorkspace, 'system-a', {promptSeries: 'arch'}) + createProject(tempWorkspace, 'system-a', {promptSeries: 'arch'}), + createProject(tempWorkspace, 'tool-a', {promptSeries: 'softwares'}) ]) const plugin = new ProjectPromptInputCapability() @@ -155,11 +160,14 @@ describe('project prompt input plugin workspace prompt support', () => { const projects = result.workspace?.projects ?? [] const extProject = projects.find(project => project.name === 'plugin-a') const archProject = projects.find(project => project.name === 'system-a') + const softwareProject = projects.find(project => project.name === 'tool-a') expect(extProject?.rootMemoryPrompt?.content).toContain('Ext root prompt') expect(extProject?.childMemoryPrompts?.[0]?.content).toContain('Ext child prompt') expect(archProject?.rootMemoryPrompt?.content).toContain('Arch root prompt') expect(archProject?.childMemoryPrompts?.[0]?.content).toContain('Arch child prompt') + expect(softwareProject?.rootMemoryPrompt?.content).toContain('Software root prompt') + expect(softwareProject?.childMemoryPrompts?.[0]?.content).toContain('Software child prompt') } finally { fs.rmSync(tempWorkspace, {recursive: true, force: true}) diff --git a/cli/src/inputs/input-readme.test.ts b/cli/src/inputs/input-readme.test.ts index fc46e3c..9b4eec8 100644 --- a/cli/src/inputs/input-readme.test.ts +++ b/cli/src/inputs/input-readme.test.ts @@ -19,7 +19,7 @@ function createContext(tempWorkspace: string, logger: InputCapabilityContext['lo } describe('readme input capability project series validation', () => { - it('fails fast when app, ext, and arch reuse the same project name', async () => { + it('fails fast when app, ext, arch, and softwares reuse the same project name', async () => { const tempWorkspace = fs.mkdtempSync(path.join(os.tmpdir(), 'tnmsc-readme-series-conflict-')) const error = vi.fn() const logger = { @@ -33,7 +33,7 @@ describe('readme input capability project series validation', () => { try { fs.mkdirSync(path.join(tempWorkspace, 'aindex', 'app', 'project-a'), {recursive: true}) - fs.mkdirSync(path.join(tempWorkspace, 'aindex', 'ext', 'project-a'), {recursive: true}) + fs.mkdirSync(path.join(tempWorkspace, 'aindex', 'softwares', 'project-a'), {recursive: true}) await expect(new ReadmeMdInputCapability().collect(createContext(tempWorkspace, logger))) .rejects diff --git a/cli/src/inputs/input-readme.ts b/cli/src/inputs/input-readme.ts index 82c60e6..d1fcb11 100644 --- a/cli/src/inputs/input-readme.ts +++ b/cli/src/inputs/input-readme.ts @@ -48,13 +48,13 @@ export class ReadmeMdInputCapability extends AbstractInputCapability { if (conflicts.length > 0) { logger.error(buildConfigDiagnostic({ code: 'README_PROJECT_SERIES_NAME_CONFLICT', - title: 'Readme project names must be unique across app, ext, and arch', + title: 'Readme project names must be unique across app, ext, arch, and softwares', reason: diagnosticLines( - 'Readme-family outputs target bare workspace project directories, so app/ext/arch cannot reuse the same project directory name.', + 'Readme-family outputs target bare workspace project directories, so app/ext/arch/softwares cannot reuse the same project directory name.', `Conflicting project names: ${conflicts.map(conflict => conflict.projectName).join(', ')}` ), exactFix: diagnosticLines( - 'Rename the conflicting project directory in one of the app/ext/arch source trees and rerun tnmsc.' + 'Rename the conflicting project directory in one of the app/ext/arch/softwares source trees and rerun tnmsc.' ), possibleFixes: conflicts.map(conflict => diagnosticLines( `"${conflict.projectName}" is currently declared in: ${conflict.refs.map(ref => `${ref.seriesName} (${ref.seriesDir})`).join(', ')}` diff --git a/cli/src/plugins/plugin-core/AindexConfigDefaults.ts b/cli/src/plugins/plugin-core/AindexConfigDefaults.ts new file mode 100644 index 0000000..8a6e748 --- /dev/null +++ b/cli/src/plugins/plugin-core/AindexConfigDefaults.ts @@ -0,0 +1,123 @@ +export interface AindexDirPairLike { + readonly src: string + readonly dist: string +} + +export const AINDEX_DEFAULT_DIR_NAME = 'aindex' + +export const AINDEX_PROJECT_SERIES_NAMES = ['app', 'ext', 'arch', 'softwares'] as const + +export type AindexProjectSeriesName = (typeof AINDEX_PROJECT_SERIES_NAMES)[number] + +export const AINDEX_CONFIG_DIRECTORY_PAIR_KEYS = [ + 'skills', + 'commands', + 'subAgents', + 'rules', + ...AINDEX_PROJECT_SERIES_NAMES +] as const + +export const AINDEX_CONFIG_FILE_PAIR_KEYS = [ + 'globalPrompt', + 'workspacePrompt' +] as const + +export const AINDEX_CONFIG_PAIR_KEYS = [ + 'skills', + 'commands', + 'subAgents', + 'rules', + 'globalPrompt', + 'workspacePrompt', + ...AINDEX_PROJECT_SERIES_NAMES +] as const + +export type AindexConfigPairKey = (typeof AINDEX_CONFIG_PAIR_KEYS)[number] +export type AindexConfigDirectoryPairKey = (typeof AINDEX_CONFIG_DIRECTORY_PAIR_KEYS)[number] +export type AindexConfigFilePairKey = (typeof AINDEX_CONFIG_FILE_PAIR_KEYS)[number] +export type AindexConfigKeyPath = `aindex.${AindexConfigPairKey}.src` | `aindex.${AindexConfigPairKey}.dist` + +export const AINDEX_PROMPT_TREE_DIRECTORY_PAIR_KEYS = [ + 'skills', + 'commands', + 'subAgents', + ...AINDEX_PROJECT_SERIES_NAMES +] as const satisfies readonly AindexConfigDirectoryPairKey[] + +export type AindexPromptTreeDirectoryPairKey = (typeof AINDEX_PROMPT_TREE_DIRECTORY_PAIR_KEYS)[number] + +interface MutableAindexDirPair { + src: string + dist: string +} + +export type AindexConfigLike = { + dir: string +} & { + [K in AindexConfigPairKey]: MutableAindexDirPair +} + +export const AINDEX_CONFIG_PAIR_DEFAULTS = { + skills: {src: 'skills', dist: 'dist/skills'}, + commands: {src: 'commands', dist: 'dist/commands'}, + subAgents: {src: 'subagents', dist: 'dist/subagents'}, + rules: {src: 'rules', dist: 'dist/rules'}, + globalPrompt: {src: 'global.src.mdx', dist: 'dist/global.mdx'}, + workspacePrompt: {src: 'workspace.src.mdx', dist: 'dist/workspace.mdx'}, + app: {src: 'app', dist: 'dist/app'}, + ext: {src: 'ext', dist: 'dist/ext'}, + arch: {src: 'arch', dist: 'dist/arch'}, + softwares: {src: 'softwares', dist: 'dist/softwares'} +} as const satisfies Record + +function buildAindexConfigKeyPaths(): readonly AindexConfigKeyPath[] { + const paths: AindexConfigKeyPath[] = [] + for (const key of AINDEX_CONFIG_PAIR_KEYS) { + paths.push(`aindex.${key}.src`, `aindex.${key}.dist`) + } + return paths +} + +function cloneAindexConfigPairs(): {[K in AindexConfigPairKey]: MutableAindexDirPair} { + return Object.fromEntries( + AINDEX_CONFIG_PAIR_KEYS.map(key => [ + key, + { + ...AINDEX_CONFIG_PAIR_DEFAULTS[key] + } + ]) + ) as {[K in AindexConfigPairKey]: MutableAindexDirPair} +} + +export const AINDEX_CONFIG_KEY_PATHS = buildAindexConfigKeyPaths() + +export function buildDefaultAindexConfig(): AindexConfigLike { + return { + dir: AINDEX_DEFAULT_DIR_NAME, + ...cloneAindexConfigPairs() + } +} + +export function mergeAindexConfig( + base: T, + override?: Partial +): T { + if (override == null) return base + + const mergedPairs = Object.fromEntries( + AINDEX_CONFIG_PAIR_KEYS.map(key => [ + key, + { + ...base[key], + ...override[key] + } + ]) + ) as {[K in AindexConfigPairKey]: T[K]} + + return { + ...base, + ...override, + dir: override.dir ?? base.dir, + ...mergedPairs + } +} diff --git a/cli/src/plugins/plugin-core/AindexTypes.ts b/cli/src/plugins/plugin-core/AindexTypes.ts index 3373a68..599efff 100644 --- a/cli/src/plugins/plugin-core/AindexTypes.ts +++ b/cli/src/plugins/plugin-core/AindexTypes.ts @@ -1,3 +1,11 @@ +export { + AINDEX_PROJECT_SERIES_NAMES +} from './AindexConfigDefaults' + +export type { + AindexProjectSeriesName +} from './AindexConfigDefaults' + /** * Aindex directory structure types and constants * Used for directory structure validation and generation @@ -53,6 +61,7 @@ export interface AindexDirectory { readonly app: AindexDirectoryEntry readonly ext: AindexDirectoryEntry readonly arch: AindexDirectoryEntry + readonly softwares: AindexDirectoryEntry readonly globalMemoryFile: AindexFileEntry readonly workspaceMemoryFile: AindexFileEntry } @@ -60,6 +69,7 @@ export interface AindexDirectory { readonly app: AindexDirectoryEntry readonly ext: AindexDirectoryEntry readonly arch: AindexDirectoryEntry + readonly softwares: AindexDirectoryEntry /** IDE configuration directories */ readonly ide: { readonly idea: AindexDirectoryEntry @@ -73,10 +83,6 @@ export interface AindexDirectory { readonly ignoreFiles: readonly AindexFileEntry[] } -export const AINDEX_PROJECT_SERIES_NAMES = ['app', 'ext', 'arch'] as const - -export type AindexProjectSeriesName = (typeof AINDEX_PROJECT_SERIES_NAMES)[number] - /** * Directory names used in aindex project */ @@ -90,6 +96,7 @@ export const AINDEX_DIR_NAMES = { APP: 'app', EXT: 'ext', ARCH: 'arch', + SOFTWARES: 'softwares', IDEA: '.idea', // IDE directories IDEA_CODE_STYLES: '.idea/codeStyles', VSCODE: '.vscode', @@ -135,11 +142,13 @@ export const AINDEX_RELATIVE_PATHS = { DIST_APP: 'dist/app', DIST_EXT: 'dist/ext', DIST_ARCH: 'dist/arch', + DIST_SOFTWARES: 'dist/softwares', DIST_GLOBAL_MEMORY: 'dist/global.mdx', DIST_WORKSPACE_MEMORY: 'dist/workspace.mdx', APP: 'app', // App source path (standalone at root) EXT: 'ext', - ARCH: 'arch' + ARCH: 'arch', + SOFTWARES: 'softwares' } as const /** @@ -224,6 +233,11 @@ export const DEFAULT_AINDEX_STRUCTURE: AindexDirectory = { name: AINDEX_DIR_NAMES.ARCH, required: false, description: 'Compiled architecture-specific prompts' + }, + softwares: { + name: AINDEX_DIR_NAMES.SOFTWARES, + required: false, + description: 'Compiled software-repository prompts' } }, app: { @@ -241,6 +255,11 @@ export const DEFAULT_AINDEX_STRUCTURE: AindexDirectory = { required: false, description: 'Architecture-specific prompts (standalone directory)' }, + softwares: { + name: AINDEX_DIR_NAMES.SOFTWARES, + required: false, + description: 'Software-repository prompts (standalone directory)' + }, ide: { idea: { name: AINDEX_DIR_NAMES.IDEA, diff --git a/cli/src/plugins/plugin-core/ConfigTypes.schema.ts b/cli/src/plugins/plugin-core/ConfigTypes.schema.ts index 03fd772..3bf047a 100644 --- a/cli/src/plugins/plugin-core/ConfigTypes.schema.ts +++ b/cli/src/plugins/plugin-core/ConfigTypes.schema.ts @@ -1,4 +1,9 @@ import {z} from 'zod/v3' +import { + AINDEX_CONFIG_PAIR_DEFAULTS, + AINDEX_CONFIG_PAIR_KEYS, + AINDEX_DEFAULT_DIR_NAME +} from './AindexConfigDefaults' /** * Zod schema for a source/dist path pair. @@ -6,21 +11,25 @@ import {z} from 'zod/v3' */ export const ZAindexDirPair = z.object({src: z.string(), dist: z.string()}) +const AINDEX_CONFIG_PAIR_SCHEMAS = Object.fromEntries( + AINDEX_CONFIG_PAIR_KEYS.map(key => [ + key, + key === 'softwares' + ? ZAindexDirPair.default(AINDEX_CONFIG_PAIR_DEFAULTS[key]) + : ZAindexDirPair + ]) +) as Record< + (typeof AINDEX_CONFIG_PAIR_KEYS)[number], + typeof ZAindexDirPair | z.ZodDefault +> + /** * Zod schema for the aindex configuration. * All paths are relative to /. */ export const ZAindexConfig = z.object({ - dir: z.string().default('aindex'), - skills: ZAindexDirPair, - commands: ZAindexDirPair, - subAgents: ZAindexDirPair, - rules: ZAindexDirPair, - globalPrompt: ZAindexDirPair, - workspacePrompt: ZAindexDirPair, - app: ZAindexDirPair, - ext: ZAindexDirPair, - arch: ZAindexDirPair + dir: z.string().default(AINDEX_DEFAULT_DIR_NAME), + ...AINDEX_CONFIG_PAIR_SCHEMAS }) /** diff --git a/cli/src/plugins/plugin-core/types.ts b/cli/src/plugins/plugin-core/types.ts index d1e6a5a..3a766df 100644 --- a/cli/src/plugins/plugin-core/types.ts +++ b/cli/src/plugins/plugin-core/types.ts @@ -1,3 +1,4 @@ +export * from './AindexConfigDefaults' export * from './AindexTypes' export * from './ConfigTypes.schema' export * from './enums' diff --git a/cli/src/prompts.test.ts b/cli/src/prompts.test.ts index 51346f4..add5c69 100644 --- a/cli/src/prompts.test.ts +++ b/cli/src/prompts.test.ts @@ -124,6 +124,17 @@ describe('prompt catalog service', () => { new Date(now + 1_000) ) + writeFile( + path.join(aindexDir, 'softwares', 'tool-a', 'agt.src.mdx'), + '---\ndescription: software project zh\n---\nSoftware project zh', + new Date(now) + ) + writeFile( + path.join(aindexDir, 'dist', 'softwares', 'tool-a', 'agt.mdx'), + '---\ndescription: software project dist\n---\nSoftware project dist', + new Date(now + 1_000) + ) + writeFile( path.join(aindexDir, 'skills', 'reviewer', 'skill.src.mdx'), '---\ndescription: skill zh\n---\nSkill zh', @@ -197,6 +208,7 @@ describe('prompt catalog service', () => { 'project-memory:app/project-a', 'project-memory:arch/system-a', 'project-memory:ext/project-a', + 'project-memory:softwares/tool-a', 'rule:frontend', 'skill-child-doc:reviewer/guide', 'skill:reviewer', @@ -225,7 +237,8 @@ describe('prompt catalog service', () => { expect(filtered.map(prompt => prompt.promptId)).toEqual([ 'project-memory:app/project-a', 'project-memory:arch/system-a', - 'project-memory:ext/project-a' + 'project-memory:ext/project-a', + 'project-memory:softwares/tool-a' ]) }) diff --git a/doc/package.json b/doc/package.json index df363d3..392dba5 100644 --- a/doc/package.json +++ b/doc/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-docs", - "version": "2026.10328.106", + "version": "2026.10329.110", "private": true, "description": "Chinese-first manifesto-led documentation site for @truenine/memory-sync.", "engines": { diff --git a/gui/package.json b/gui/package.json index 5fbaf66..7a454ed 100644 --- a/gui/package.json +++ b/gui/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-gui", - "version": "2026.10328.106", + "version": "2026.10329.110", "private": true, "engines": { "node": ">=25.2.1", diff --git a/gui/src-tauri/Cargo.lock b/gui/src-tauri/Cargo.lock index 50bfc26..21b336c 100644 --- a/gui/src-tauri/Cargo.lock +++ b/gui/src-tauri/Cargo.lock @@ -1774,7 +1774,7 @@ dependencies = [ [[package]] name = "memory-sync-gui" -version = "2026.10328.106" +version = "2026.10329.110" dependencies = [ "dirs", "json5", diff --git a/gui/src-tauri/Cargo.toml b/gui/src-tauri/Cargo.toml index 6f208f4..73f767d 100644 --- a/gui/src-tauri/Cargo.toml +++ b/gui/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "memory-sync-gui" -version = "2026.10328.106" +version = "2026.10329.110" description = "Memory Sync desktop GUI application" authors.workspace = true edition.workspace = true diff --git a/gui/src-tauri/tauri.conf.json b/gui/src-tauri/tauri.conf.json index 95927e3..af5ab62 100644 --- a/gui/src-tauri/tauri.conf.json +++ b/gui/src-tauri/tauri.conf.json @@ -1,6 +1,6 @@ { "$schema": "https://schema.tauri.app/config/2", - "version": "2026.10328.106", + "version": "2026.10329.110", "productName": "Memory Sync", "identifier": "org.truenine.memory-sync", "build": { diff --git a/libraries/logger/package.json b/libraries/logger/package.json index 7e50d20..f58407b 100644 --- a/libraries/logger/package.json +++ b/libraries/logger/package.json @@ -1,7 +1,7 @@ { "name": "@truenine/logger", "type": "module", - "version": "2026.10328.106", + "version": "2026.10329.110", "private": true, "description": "Rust-powered structured logger for Node.js via N-API", "license": "AGPL-3.0-only", diff --git a/libraries/md-compiler/package.json b/libraries/md-compiler/package.json index 5fa000e..1cc34c4 100644 --- a/libraries/md-compiler/package.json +++ b/libraries/md-compiler/package.json @@ -1,7 +1,7 @@ { "name": "@truenine/md-compiler", "type": "module", - "version": "2026.10328.106", + "version": "2026.10329.110", "private": true, "description": "Rust-powered MDX→Markdown compiler for Node.js with pure-TS fallback", "license": "AGPL-3.0-only", diff --git a/libraries/script-runtime/package.json b/libraries/script-runtime/package.json index 0e11792..ce82c38 100644 --- a/libraries/script-runtime/package.json +++ b/libraries/script-runtime/package.json @@ -1,7 +1,7 @@ { "name": "@truenine/script-runtime", "type": "module", - "version": "2026.10328.106", + "version": "2026.10329.110", "private": true, "description": "Rust-backed TypeScript proxy runtime for tnmsc", "license": "AGPL-3.0-only", diff --git a/mcp/package.json b/mcp/package.json index 850483d..a333194 100644 --- a/mcp/package.json +++ b/mcp/package.json @@ -1,7 +1,7 @@ { "name": "@truenine/memory-sync-mcp", "type": "module", - "version": "2026.10328.106", + "version": "2026.10329.110", "description": "MCP stdio server for managing memory-sync prompt sources and translation artifacts", "author": "TrueNine", "license": "AGPL-3.0-only", diff --git a/package.json b/package.json index beaaab2..8607f51 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync", - "version": "2026.10328.106", + "version": "2026.10329.110", "description": "Cross-AI-tool prompt synchronisation toolkit (CLI + Tauri desktop GUI) — one ruleset, multi-target adaptation. Monorepo powered by pnpm + Turbo.", "license": "AGPL-3.0-only", "keywords": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 16f4092..1173986 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -22,8 +22,8 @@ catalogs: specifier: ^4.7.0 version: 4.7.0 '@napi-rs/cli': - specifier: ^3.5.1 - version: 3.5.1 + specifier: ^3.6.0 + version: 3.6.0 '@next/eslint-plugin-next': specifier: ^16.2.1 version: 16.2.1 @@ -31,14 +31,14 @@ catalogs: specifier: ^4.2.2 version: 4.2.2 '@tanstack/react-router': - specifier: ^1.168.7 - version: 1.168.7 + specifier: ^1.168.8 + version: 1.168.8 '@tanstack/router-generator': - specifier: ^1.166.21 - version: 1.166.21 + specifier: ^1.166.22 + version: 1.166.22 '@tanstack/router-plugin': - specifier: ^1.167.8 - version: 1.167.8 + specifier: ^1.167.9 + version: 1.167.9 '@tauri-apps/api': specifier: ^2.10.1 version: 2.10.1 @@ -202,14 +202,14 @@ catalogs: specifier: ^4.2.2 version: 4.2.2 tsdown: - specifier: ^0.21.6 - version: 0.21.6 + specifier: ^0.21.7 + version: 0.21.7 tsx: specifier: ^4.21.0 version: 4.21.0 turbo: - specifier: ^2.8.20 - version: 2.8.20 + specifier: ^2.8.21 + version: 2.8.21 tw-animate-css: specifier: ^1.4.0 version: 1.4.0 @@ -244,19 +244,19 @@ importers: devDependencies: '@antfu/eslint-config': specifier: 'catalog:' - version: 7.7.3(@next/eslint-plugin-next@16.2.1)(@typescript-eslint/rule-tester@8.56.1(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(@typescript-eslint/typescript-estree@8.57.2(typescript@6.0.2))(@typescript-eslint/utils@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(@unocss/eslint-plugin@66.6.7(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(@vue/compiler-sfc@3.5.26)(eslint-plugin-format@2.0.1(eslint@10.1.0(jiti@2.6.1)))(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2)(vitest@4.1.2(@types/node@25.5.0)(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))) + version: 7.7.3(@next/eslint-plugin-next@16.2.1)(@typescript-eslint/rule-tester@8.56.1(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(@typescript-eslint/typescript-estree@8.57.2(typescript@6.0.2))(@typescript-eslint/utils@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(@unocss/eslint-plugin@66.6.7(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(@vue/compiler-sfc@3.5.26)(eslint-plugin-format@2.0.1(eslint@10.1.0(jiti@2.6.1)))(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2)(vitest@4.1.2(@types/node@25.5.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))) '@eslint/js': specifier: 'catalog:' version: 10.0.1(eslint@10.1.0(jiti@2.6.1)) '@napi-rs/cli': specifier: 'catalog:' - version: 3.5.1(@emnapi/runtime@1.9.1)(@types/node@25.5.0) + version: 3.6.0(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0) '@next/eslint-plugin-next': specifier: 'catalog:' version: 16.2.1 '@truenine/eslint10-config': specifier: 'catalog:' - version: 2026.10326.11646(683394b0bd356ba44c1728f4f8bd41fc) + version: 2026.10326.11646(3147283cf2a5f1693493984073c80bb9) '@types/node': specifier: 'catalog:' version: 25.5.0 @@ -295,13 +295,13 @@ importers: version: 2.13.1 tsdown: specifier: 'catalog:' - version: 0.21.6(synckit@0.11.12)(typescript@6.0.2) + version: 0.21.7(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(synckit@0.11.12)(typescript@6.0.2) tsx: specifier: 'catalog:' version: 4.21.0 turbo: specifier: 'catalog:' - version: 2.8.20 + version: 2.8.21 typescript: specifier: 'catalog:' version: 6.0.2 @@ -310,10 +310,10 @@ importers: version: 8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2) vite: specifier: 'catalog:' - version: 8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) vitest: specifier: 'catalog:' - version: 4.1.2(@types/node@25.5.0)(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.2(@types/node@25.5.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) cli: dependencies: @@ -347,7 +347,7 @@ importers: version: 4.0.2 '@vitest/coverage-v8': specifier: 'catalog:' - version: 4.1.2(vitest@4.1.2(@types/node@25.5.0)(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))) + version: 4.1.2(vitest@4.1.2(@types/node@25.5.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))) fast-glob: specifier: 'catalog:' version: 3.3.3 @@ -371,7 +371,7 @@ importers: version: 4.21.0 vitest: specifier: 'catalog:' - version: 4.1.2(@types/node@25.5.0)(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.2(@types/node@25.5.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) zod-to-json-schema: specifier: 'catalog:' version: 3.25.2(zod@4.3.6) @@ -428,7 +428,7 @@ importers: devDependencies: '@truenine/eslint10-config': specifier: 'catalog:' - version: 2026.10326.11646(683394b0bd356ba44c1728f4f8bd41fc) + version: 2026.10326.11646(3147283cf2a5f1693493984073c80bb9) '@types/node': specifier: 'catalog:' version: 25.5.0 @@ -467,16 +467,16 @@ importers: version: 4.7.0(monaco-editor@0.55.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@tailwindcss/vite': specifier: 'catalog:' - version: 4.2.2(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.2.2(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) '@tanstack/react-router': specifier: 'catalog:' - version: 1.168.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + version: 1.168.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@tanstack/router-generator': specifier: 'catalog:' - version: 1.166.21 + version: 1.166.22 '@tanstack/router-plugin': specifier: 'catalog:' - version: 1.167.8(@tanstack/react-router@1.168.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 1.167.9(@tanstack/react-router@1.168.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) '@tauri-apps/api': specifier: 'catalog:' version: 2.10.1 @@ -497,7 +497,7 @@ importers: version: 19.2.3(@types/react@19.2.14) '@vitejs/plugin-react': specifier: 'catalog:' - version: 6.0.1(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 6.0.1(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) class-variance-authority: specifier: 'catalog:' version: 0.7.1 @@ -536,31 +536,31 @@ importers: version: 1.4.0 vitest: specifier: 'catalog:' - version: 4.1.2(@types/node@25.5.0)(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.2(@types/node@25.5.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) libraries/logger: devDependencies: '@napi-rs/cli': specifier: 'catalog:' - version: 3.5.1(@emnapi/runtime@1.9.1)(@types/node@25.5.0) + version: 3.6.0(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0) npm-run-all2: specifier: 'catalog:' version: 8.0.4 tsdown: specifier: 'catalog:' - version: 0.21.6(synckit@0.11.12)(typescript@6.0.2) + version: 0.21.7(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(synckit@0.11.12)(typescript@6.0.2) typescript: specifier: 'catalog:' version: 6.0.2 vitest: specifier: 'catalog:' - version: 4.1.2(@types/node@25.5.0)(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.2(@types/node@25.5.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) libraries/md-compiler: devDependencies: '@napi-rs/cli': specifier: 'catalog:' - version: 3.5.1(@emnapi/runtime@1.9.1)(@types/node@25.5.0) + version: 3.6.0(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0) '@types/estree': specifier: 'catalog:' version: 1.0.8 @@ -593,7 +593,7 @@ importers: version: 11.0.0 tsdown: specifier: 'catalog:' - version: 0.21.6(synckit@0.11.12)(typescript@6.0.2) + version: 0.21.7(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(synckit@0.11.12)(typescript@6.0.2) typescript: specifier: 'catalog:' version: 6.0.2 @@ -602,7 +602,7 @@ importers: version: 11.0.5 vitest: specifier: 'catalog:' - version: 4.1.2(@types/node@25.5.0)(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.2(@types/node@25.5.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) yaml: specifier: 'catalog:' version: 2.8.3 @@ -611,10 +611,10 @@ importers: devDependencies: '@napi-rs/cli': specifier: 'catalog:' - version: 3.5.1(@emnapi/runtime@1.9.1)(@types/node@25.5.0) + version: 3.6.0(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0) '@truenine/eslint10-config': specifier: 'catalog:' - version: 2026.10326.11646(683394b0bd356ba44c1728f4f8bd41fc) + version: 2026.10326.11646(3147283cf2a5f1693493984073c80bb9) '@types/node': specifier: 'catalog:' version: 25.5.0 @@ -629,13 +629,13 @@ importers: version: 8.0.4 tsdown: specifier: 'catalog:' - version: 0.21.6(synckit@0.11.12)(typescript@6.0.2) + version: 0.21.7(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(synckit@0.11.12)(typescript@6.0.2) typescript: specifier: 'catalog:' version: 6.0.2 vitest: specifier: 'catalog:' - version: 4.1.2(@types/node@25.5.0)(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.2(@types/node@25.5.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) mcp: dependencies: @@ -651,7 +651,7 @@ importers: devDependencies: '@truenine/eslint10-config': specifier: 'catalog:' - version: 2026.10326.11646(683394b0bd356ba44c1728f4f8bd41fc) + version: 2026.10326.11646(3147283cf2a5f1693493984073c80bb9) '@types/node': specifier: 'catalog:' version: 25.5.0 @@ -663,7 +663,7 @@ importers: version: 8.0.4 tsdown: specifier: 'catalog:' - version: 0.21.6(synckit@0.11.12)(typescript@6.0.2) + version: 0.21.7(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(synckit@0.11.12)(typescript@6.0.2) tsx: specifier: 'catalog:' version: 4.21.0 @@ -672,7 +672,7 @@ importers: version: 6.0.2 vitest: specifier: 'catalog:' - version: 4.1.2(@types/node@25.5.0)(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.1.2(@types/node@25.5.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) packages: @@ -1522,8 +1522,8 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@napi-rs/cli@3.5.1': - resolution: {integrity: sha512-XBfLQRDcB3qhu6bazdMJsecWW55kR85l5/k0af9BIBELXQSsCFU0fzug7PX8eQp6vVdm7W/U3z6uP5WmITB2Gw==} + '@napi-rs/cli@3.6.0': + resolution: {integrity: sha512-aA8m4+9XxnK1+0sr4GplZP0Ze90gkzO8sMKaplOK0zXbLnzsLl6O2BQQt6rTCcTRzIN24wrrByakr/imM+CxhA==} engines: {node: '>= 16'} hasBin: true peerDependencies: @@ -1884,8 +1884,11 @@ packages: resolution: {integrity: sha512-7cmzIu+Vbupriudo7UudoMRH2OA3cTw67vva8MxeoAe5S7vPFI7z0vp0pMXiA25S8IUJefImQ90FeJjl8fjEaQ==} engines: {node: '>= 10'} - '@napi-rs/wasm-runtime@1.1.1': - resolution: {integrity: sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==} + '@napi-rs/wasm-runtime@1.1.2': + resolution: {integrity: sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 '@napi-rs/wasm-tools-android-arm-eabi@1.0.1': resolution: {integrity: sha512-lr07E/l571Gft5v4aA1dI8koJEmF1F0UigBbsqg9OWNzg80H3lDPO+auv85y3T/NHE3GirDk7x/D3sLO57vayw==} @@ -2555,8 +2558,8 @@ packages: resolution: {integrity: sha512-NaOGLRrddszbQj9upGat6HG/4TKvXLvu+osAIgfxPYA+eIvYKv8GKDJOrY2D3/U9MRnKfMWD7bU4jeD4xmqyIg==} engines: {node: '>=20.19'} - '@tanstack/react-router@1.168.7': - resolution: {integrity: sha512-fW/HvQja4PQeu9lsoyh+pXpZ0UXezbpQkkJvCuH6tHAaW3jvPkjh14lfadrNNiY+pXT7WiMTB3afGhTCC78PDQ==} + '@tanstack/react-router@1.168.8': + resolution: {integrity: sha512-t0S0QueXubBKmI9eLPcN/A1sLQgTu8/yHerjrvvsGeD12zMdw0uJPKwEKpStQF2OThQtw64cs34uUSYXBUTSNw==} engines: {node: '>=20.19'} peerDependencies: react: '>=18.0.0 || >=19.0.0' @@ -2574,22 +2577,22 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - '@tanstack/router-core@1.168.6': - resolution: {integrity: sha512-okCno3pImpLFQMJ/4zqEIGjIV5yhxLGj0JByrzQDQehORN1y1q6lJUezT0KPK5qCQiKUApeWaboLPjgBVx1kaQ==} + '@tanstack/router-core@1.168.7': + resolution: {integrity: sha512-z4UEdlzMrFaKBsG4OIxlZEm+wsYBtEp//fnX6kW18jhQpETNcM6u2SXNdX+bcIYp6AaR7ERS3SBENzjC/xxwQQ==} engines: {node: '>=20.19'} hasBin: true - '@tanstack/router-generator@1.166.21': - resolution: {integrity: sha512-pJWsP6HaGrkIkfkcg6vzKyCBMbf1vV1BrQH+bFAVzXj3T/afmix3IPV2hiAj4zzjMxuddJD1on0Hn5+WDYA7zQ==} + '@tanstack/router-generator@1.166.22': + resolution: {integrity: sha512-wQ7H8/Q2rmSPuaxWnurJ3DATNnqWV2tajxri9TSiW4QHsG7cWPD34+goeIinKG+GajJyEdfVpz6w/gRJXfbAPw==} engines: {node: '>=20.19'} - '@tanstack/router-plugin@1.167.8': - resolution: {integrity: sha512-/X4ACYsSX4bRmomj5X2TBU75cHuIVI99Fsax6DWnP6hPb4PaSjPUHVBfHhk2NemJzEOZu1L31UQ9QDlbHU4ZTQ==} + '@tanstack/router-plugin@1.167.9': + resolution: {integrity: sha512-h/VV05FEHd4PVyc5Zy8B3trWLcdLt/Pmp+mfifmBKGRw+MUtvdQKbBHhmy4ouOf67s5zDJMc+n8R3xgU7bDwFA==} engines: {node: '>=20.19'} hasBin: true peerDependencies: '@rsbuild/core': '>=1.0.2' - '@tanstack/react-router': ^1.168.7 + '@tanstack/react-router': ^1.168.8 vite: '>=5.0.0 || >=6.0.0 || >=7.0.0' vite-plugin-solid: ^2.11.10 webpack: '>=5.92.0' @@ -2732,33 +2735,33 @@ packages: '@ts-morph/common@0.28.1': resolution: {integrity: sha512-W74iWf7ILp1ZKNYXY5qbddNaml7e9Sedv5lvU1V8lftlitkc9Pq1A+jlH23ltDgWYeZFFEqGCD1Ies9hqu3O+g==} - '@turbo/darwin-64@2.8.20': - resolution: {integrity: sha512-FQ9EX1xMU5nbwjxXxM3yU88AQQ6Sqc6S44exPRroMcx9XZHqqppl5ymJF0Ig/z3nvQNwDmz1Gsnvxubo+nXWjQ==} + '@turbo/darwin-64@2.8.21': + resolution: {integrity: sha512-kfGoM0Iw8ZNZpbds+4IzOe0hjvHldqJwUPRAjXJi3KBxg/QOZL95N893SRoMtf2aJ+jJ3dk32yPkp8rvcIjP9g==} cpu: [x64] os: [darwin] - '@turbo/darwin-arm64@2.8.20': - resolution: {integrity: sha512-Gpyh9ATFGThD6/s9L95YWY54cizg/VRWl2B67h0yofG8BpHf67DFAh9nuJVKG7bY0+SBJDAo5cMur+wOl9YOYw==} + '@turbo/darwin-arm64@2.8.21': + resolution: {integrity: sha512-o9HEflxUEyr987x0cTUzZBhDOyL6u95JmdmlkH2VyxAw7zq2sdtM5e72y9ufv2N5SIoOBw1fVn9UES5VY5H6vQ==} cpu: [arm64] os: [darwin] - '@turbo/linux-64@2.8.20': - resolution: {integrity: sha512-p2QxWUYyYUgUFG0b0kR+pPi8t7c9uaVlRtjTTI1AbCvVqkpjUfCcReBn6DgG/Hu8xrWdKLuyQFaLYFzQskZbcA==} + '@turbo/linux-64@2.8.21': + resolution: {integrity: sha512-uTxlCcXWy5h1fSSymP8XSJ+AudzEHMDV3IDfKX7+DGB8kgJ+SLoTUAH7z4OFA7I/l2sznz0upPdbNNZs91YMag==} cpu: [x64] os: [linux] - '@turbo/linux-arm64@2.8.20': - resolution: {integrity: sha512-Gn5yjlZGLRZWarLWqdQzv0wMqyBNIdq1QLi48F1oY5Lo9kiohuf7BPQWtWxeNVS2NgJ1+nb/DzK1JduYC4AWOA==} + '@turbo/linux-arm64@2.8.21': + resolution: {integrity: sha512-cdHIcxNcihHHkCHp0Y4Zb60K4Qz+CK4xw1gb6s/t/9o4SMeMj+hTBCtoW6QpPnl9xPYmxuTou8Zw6+cylTnREg==} cpu: [arm64] os: [linux] - '@turbo/windows-64@2.8.20': - resolution: {integrity: sha512-vyaDpYk/8T6Qz5V/X+ihKvKFEZFUoC0oxYpC1sZanK6gaESJlmV3cMRT3Qhcg4D2VxvtC2Jjs9IRkrZGL+exLw==} + '@turbo/windows-64@2.8.21': + resolution: {integrity: sha512-/iBj4OzbqEY8CX+eaeKbBTMZv2CLXNrt0692F7HnK7LcyYwyDecaAiSET6ZzL4opT7sbwkKvzAC/fhqT3Quu1A==} cpu: [x64] os: [win32] - '@turbo/windows-arm64@2.8.20': - resolution: {integrity: sha512-voicVULvUV5yaGXo0Iue13BcHGYW3u0VgqSbfQwBaHbpj1zLjYV4KIe+7fYIo6DO8FVUJzxFps3ODCQG/Wy2Qw==} + '@turbo/windows-arm64@2.8.21': + resolution: {integrity: sha512-95tMA/ZbIidJFUUtkmqioQ1gf3n3I1YbRP3ZgVdWTVn2qVbkodcIdGXBKRHHrIbRsLRl99SiHi/L7IxhpZDagQ==} cpu: [arm64] os: [win32] @@ -3259,8 +3262,8 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} - baseline-browser-mapping@2.10.11: - resolution: {integrity: sha512-DAKrHphkJyiGuau/cFieRYhcTFeK/lBuD++C7cZ6KZHbMhBrisoi+EvhQ5RZrIfV5qwsW8kgQ07JIC+MDJRAhg==} + baseline-browser-mapping@2.10.12: + resolution: {integrity: sha512-qyq26DxfY4awP2gIRXhhLWfwzwI+N5Nxk6iQi8EFizIaWIjqicQTE4sLnZZVdeKPRcVNoJOkkpfzoIYuvCKaIQ==} engines: {node: '>=6.0.0'} hasBin: true @@ -3425,6 +3428,10 @@ packages: resolution: {integrity: sha512-aRDkn3uyIlCFfk5NUA+VdwMmMsh8JGhc4hapfV4yxymHGQ3BVskMQfoXGpCo5IoBuQ9tS5iiVKhCpTcB4pW4qw==} engines: {node: '>= 12.0.0'} + comment-parser@1.4.6: + resolution: {integrity: sha512-ObxuY6vnbWTN6Od72xfwN9DbzC7Y2vv8u1Soi9ahRKL37gb6y1qk6/dgjs+3JWuXJHWvsg3BXIwzd/rkmAwavg==} + engines: {node: '>= 12.0.0'} + compute-scroll-into-view@3.1.1: resolution: {integrity: sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==} @@ -5429,8 +5436,8 @@ packages: robust-predicates@3.0.3: resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==} - rolldown-plugin-dts@0.23.1: - resolution: {integrity: sha512-VTnvu5cksnumMMOiL7FUvACGpdGtCVNGbeVc6/6KffImIrA0DZOp7/0lBIt0qI6Nu3/K/lL/Dy7piuVGt9ZeGw==} + rolldown-plugin-dts@0.23.2: + resolution: {integrity: sha512-PbSqLawLgZBGcOGT3yqWBGn4cX+wh2nt5FuBGdcMHyOhoukmjbhYAl8NT9sE4U38Cm9tqLOIQeOrvzeayM0DLQ==} engines: {node: '>=20.19.0'} peerDependencies: '@ts-macro/tsc': ^0.3.6 @@ -5737,14 +5744,14 @@ packages: ts-morph@27.0.2: resolution: {integrity: sha512-fhUhgeljcrdZ+9DZND1De1029PrE+cMkIP7ooqkLRTrRLTqcki2AstsyJm0vRNbTbVCNJ0idGlbBrfqc7/nA8w==} - tsdown@0.21.6: - resolution: {integrity: sha512-YsgPuWczqxPkXiJwMPrv3eOiqx4KPhOdksqubVCDhS7lChK3RYlWsEGhZixc0+lqN3fmBYEnETaujEWDpMPZmA==} + tsdown@0.21.7: + resolution: {integrity: sha512-ukKIxKQzngkWvOYJAyptudclkm4VQqbjq+9HF5K5qDO8GJsYtMh8gIRwicbnZEnvFPr6mquFwYAVZ8JKt3rY2g==} engines: {node: '>=20.19.0'} hasBin: true peerDependencies: '@arethetypeswrong/core': ^0.18.1 - '@tsdown/css': 0.21.6 - '@tsdown/exe': 0.21.6 + '@tsdown/css': 0.21.7 + '@tsdown/exe': 0.21.7 '@vitejs/devtools': '*' publint: ^0.3.0 typescript: ^5.0.0 || ^6.0.0 @@ -5773,8 +5780,8 @@ packages: engines: {node: '>=18.0.0'} hasBin: true - turbo@2.8.20: - resolution: {integrity: sha512-Rb4qk5YT8RUwwdXtkLpkVhNEe/lor6+WV7S5tTlLpxSz6MjV5Qi8jGNn4gS6NAvrYGA/rNrE6YUQM85sCZUDbQ==} + turbo@2.8.21: + resolution: {integrity: sha512-FlJ8OD5Qcp0jTAM7E4a/RhUzRNds2GzKlyxHKA6N247VLy628rrxAGlMpIXSz6VB430+TiQDJ/SMl6PL1lu6wQ==} hasBin: true tw-animate-css@1.4.0: @@ -6116,7 +6123,7 @@ packages: snapshots: - '@antfu/eslint-config@7.7.3(@next/eslint-plugin-next@16.2.1)(@typescript-eslint/rule-tester@8.56.1(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(@typescript-eslint/typescript-estree@8.57.2(typescript@6.0.2))(@typescript-eslint/utils@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(@unocss/eslint-plugin@66.6.7(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(@vue/compiler-sfc@3.5.26)(eslint-plugin-format@2.0.1(eslint@10.1.0(jiti@2.6.1)))(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2)(vitest@4.1.2(@types/node@25.5.0)(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)))': + '@antfu/eslint-config@7.7.3(@next/eslint-plugin-next@16.2.1)(@typescript-eslint/rule-tester@8.56.1(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(@typescript-eslint/typescript-estree@8.57.2(typescript@6.0.2))(@typescript-eslint/utils@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(@unocss/eslint-plugin@66.6.7(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(@vue/compiler-sfc@3.5.26)(eslint-plugin-format@2.0.1(eslint@10.1.0(jiti@2.6.1)))(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2)(vitest@4.1.2(@types/node@25.5.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: '@antfu/install-pkg': 1.1.0 '@clack/prompts': 1.1.0 @@ -6126,7 +6133,7 @@ snapshots: '@stylistic/eslint-plugin': 5.10.0(eslint@10.1.0(jiti@2.6.1)) '@typescript-eslint/eslint-plugin': 8.57.2(@typescript-eslint/parser@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2) '@typescript-eslint/parser': 8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2) - '@vitest/eslint-plugin': 1.6.13(@typescript-eslint/eslint-plugin@8.57.2(@typescript-eslint/parser@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2)(vitest@4.1.2(@types/node@25.5.0)(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))) + '@vitest/eslint-plugin': 1.6.13(@typescript-eslint/eslint-plugin@8.57.2(@typescript-eslint/parser@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2)(vitest@4.1.2(@types/node@25.5.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))) ansis: 4.2.0 cac: 7.0.0 eslint: 10.1.0(jiti@2.6.1) @@ -6888,11 +6895,11 @@ snapshots: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@napi-rs/cli@3.5.1(@emnapi/runtime@1.9.1)(@types/node@25.5.0)': + '@napi-rs/cli@3.6.0(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)': dependencies: '@inquirer/prompts': 8.3.2(@types/node@25.5.0) - '@napi-rs/cross-toolchain': 1.0.3 - '@napi-rs/wasm-tools': 1.0.1 + '@napi-rs/cross-toolchain': 1.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1) + '@napi-rs/wasm-tools': 1.0.1(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1) '@octokit/rest': 22.0.1 clipanion: 4.0.0-rc.4(typanion@3.14.0) colorette: 2.0.20 @@ -6905,6 +6912,7 @@ snapshots: optionalDependencies: '@emnapi/runtime': 1.9.1 transitivePeerDependencies: + - '@emnapi/core' - '@napi-rs/cross-toolchain-arm64-target-aarch64' - '@napi-rs/cross-toolchain-arm64-target-armv7' - '@napi-rs/cross-toolchain-arm64-target-ppc64le' @@ -6919,12 +6927,14 @@ snapshots: - node-addon-api - supports-color - '@napi-rs/cross-toolchain@1.0.3': + '@napi-rs/cross-toolchain@1.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)': dependencies: - '@napi-rs/lzma': 1.4.5 - '@napi-rs/tar': 1.1.0 + '@napi-rs/lzma': 1.4.5(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1) + '@napi-rs/tar': 1.1.0(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1) debug: 4.4.3 transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' - supports-color '@napi-rs/lzma-android-arm-eabi@1.4.5': @@ -6966,9 +6976,12 @@ snapshots: '@napi-rs/lzma-linux-x64-musl@1.4.5': optional: true - '@napi-rs/lzma-wasm32-wasi@1.4.5': + '@napi-rs/lzma-wasm32-wasi@1.4.5(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)': dependencies: - '@napi-rs/wasm-runtime': 1.1.1 + '@napi-rs/wasm-runtime': 1.1.2(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' optional: true '@napi-rs/lzma-win32-arm64-msvc@1.4.5': @@ -6980,7 +6993,7 @@ snapshots: '@napi-rs/lzma-win32-x64-msvc@1.4.5': optional: true - '@napi-rs/lzma@1.4.5': + '@napi-rs/lzma@1.4.5(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)': optionalDependencies: '@napi-rs/lzma-android-arm-eabi': 1.4.5 '@napi-rs/lzma-android-arm64': 1.4.5 @@ -6995,10 +7008,13 @@ snapshots: '@napi-rs/lzma-linux-s390x-gnu': 1.4.5 '@napi-rs/lzma-linux-x64-gnu': 1.4.5 '@napi-rs/lzma-linux-x64-musl': 1.4.5 - '@napi-rs/lzma-wasm32-wasi': 1.4.5 + '@napi-rs/lzma-wasm32-wasi': 1.4.5(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1) '@napi-rs/lzma-win32-arm64-msvc': 1.4.5 '@napi-rs/lzma-win32-ia32-msvc': 1.4.5 '@napi-rs/lzma-win32-x64-msvc': 1.4.5 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' '@napi-rs/simple-git-android-arm-eabi@0.1.22': optional: true @@ -7099,9 +7115,12 @@ snapshots: '@napi-rs/tar-linux-x64-musl@1.1.0': optional: true - '@napi-rs/tar-wasm32-wasi@1.1.0': + '@napi-rs/tar-wasm32-wasi@1.1.0(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)': dependencies: - '@napi-rs/wasm-runtime': 1.1.1 + '@napi-rs/wasm-runtime': 1.1.2(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' optional: true '@napi-rs/tar-win32-arm64-msvc@1.1.0': @@ -7113,7 +7132,7 @@ snapshots: '@napi-rs/tar-win32-x64-msvc@1.1.0': optional: true - '@napi-rs/tar@1.1.0': + '@napi-rs/tar@1.1.0(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)': optionalDependencies: '@napi-rs/tar-android-arm-eabi': 1.1.0 '@napi-rs/tar-android-arm64': 1.1.0 @@ -7127,12 +7146,15 @@ snapshots: '@napi-rs/tar-linux-s390x-gnu': 1.1.0 '@napi-rs/tar-linux-x64-gnu': 1.1.0 '@napi-rs/tar-linux-x64-musl': 1.1.0 - '@napi-rs/tar-wasm32-wasi': 1.1.0 + '@napi-rs/tar-wasm32-wasi': 1.1.0(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1) '@napi-rs/tar-win32-arm64-msvc': 1.1.0 '@napi-rs/tar-win32-ia32-msvc': 1.1.0 '@napi-rs/tar-win32-x64-msvc': 1.1.0 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' - '@napi-rs/wasm-runtime@1.1.1': + '@napi-rs/wasm-runtime@1.1.2(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)': dependencies: '@emnapi/core': 1.9.1 '@emnapi/runtime': 1.9.1 @@ -7166,9 +7188,12 @@ snapshots: '@napi-rs/wasm-tools-linux-x64-musl@1.0.1': optional: true - '@napi-rs/wasm-tools-wasm32-wasi@1.0.1': + '@napi-rs/wasm-tools-wasm32-wasi@1.0.1(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)': dependencies: - '@napi-rs/wasm-runtime': 1.1.1 + '@napi-rs/wasm-runtime': 1.1.2(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' optional: true '@napi-rs/wasm-tools-win32-arm64-msvc@1.0.1': @@ -7180,7 +7205,7 @@ snapshots: '@napi-rs/wasm-tools-win32-x64-msvc@1.0.1': optional: true - '@napi-rs/wasm-tools@1.0.1': + '@napi-rs/wasm-tools@1.0.1(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)': optionalDependencies: '@napi-rs/wasm-tools-android-arm-eabi': 1.0.1 '@napi-rs/wasm-tools-android-arm64': 1.0.1 @@ -7191,10 +7216,13 @@ snapshots: '@napi-rs/wasm-tools-linux-arm64-musl': 1.0.1 '@napi-rs/wasm-tools-linux-x64-gnu': 1.0.1 '@napi-rs/wasm-tools-linux-x64-musl': 1.0.1 - '@napi-rs/wasm-tools-wasm32-wasi': 1.0.1 + '@napi-rs/wasm-tools-wasm32-wasi': 1.0.1(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1) '@napi-rs/wasm-tools-win32-arm64-msvc': 1.0.1 '@napi-rs/wasm-tools-win32-ia32-msvc': 1.0.1 '@napi-rs/wasm-tools-win32-x64-msvc': 1.0.1 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' '@next/env@16.2.1': {} @@ -7483,9 +7511,12 @@ snapshots: '@rolldown/binding-openharmony-arm64@1.0.0-rc.12': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-rc.12': + '@rolldown/binding-wasm32-wasi@1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)': dependencies: - '@napi-rs/wasm-runtime': 1.1.1 + '@napi-rs/wasm-runtime': 1.1.2(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' optional: true '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.12': @@ -7625,20 +7656,20 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.2.2 '@tailwindcss/oxide-win32-x64-msvc': 4.2.2 - '@tailwindcss/vite@4.2.2(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))': + '@tailwindcss/vite@4.2.2(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@tailwindcss/node': 4.2.2 '@tailwindcss/oxide': 4.2.2 tailwindcss: 4.2.2 - vite: 8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) '@tanstack/history@1.161.6': {} - '@tanstack/react-router@1.168.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + '@tanstack/react-router@1.168.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: '@tanstack/history': 1.161.6 '@tanstack/react-store': 0.9.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@tanstack/router-core': 1.168.6 + '@tanstack/router-core': 1.168.7 isbot: 5.1.36 react: 19.2.4 react-dom: 19.2.4(react@19.2.4) @@ -7656,16 +7687,16 @@ snapshots: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - '@tanstack/router-core@1.168.6': + '@tanstack/router-core@1.168.7': dependencies: '@tanstack/history': 1.161.6 cookie-es: 2.0.0 seroval: 1.5.1 seroval-plugins: 1.5.1(seroval@1.5.1) - '@tanstack/router-generator@1.166.21': + '@tanstack/router-generator@1.166.22': dependencies: - '@tanstack/router-core': 1.168.6 + '@tanstack/router-core': 1.168.7 '@tanstack/router-utils': 1.161.6 '@tanstack/virtual-file-routes': 1.161.7 prettier: 3.8.1 @@ -7676,7 +7707,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.167.8(@tanstack/react-router@1.168.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))': + '@tanstack/router-plugin@1.167.9(@tanstack/react-router@1.168.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) @@ -7684,16 +7715,16 @@ snapshots: '@babel/template': 7.28.6 '@babel/traverse': 7.29.0 '@babel/types': 7.29.0 - '@tanstack/router-core': 1.168.6 - '@tanstack/router-generator': 1.166.21 + '@tanstack/router-core': 1.168.7 + '@tanstack/router-generator': 1.166.22 '@tanstack/router-utils': 1.161.6 '@tanstack/virtual-file-routes': 1.161.7 chokidar: 3.6.0 unplugin: 2.3.11 zod: 3.25.76 optionalDependencies: - '@tanstack/react-router': 1.168.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - vite: 8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + '@tanstack/react-router': 1.168.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + vite: 8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) transitivePeerDependencies: - supports-color @@ -7785,9 +7816,9 @@ snapshots: npm-to-yarn: 3.0.1 unist-util-visit: 5.1.0 - '@truenine/eslint10-config@2026.10326.11646(683394b0bd356ba44c1728f4f8bd41fc)': + '@truenine/eslint10-config@2026.10326.11646(3147283cf2a5f1693493984073c80bb9)': dependencies: - '@antfu/eslint-config': 7.7.3(@next/eslint-plugin-next@16.2.1)(@typescript-eslint/rule-tester@8.56.1(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(@typescript-eslint/typescript-estree@8.57.2(typescript@6.0.2))(@typescript-eslint/utils@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(@unocss/eslint-plugin@66.6.7(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(@vue/compiler-sfc@3.5.26)(eslint-plugin-format@2.0.1(eslint@10.1.0(jiti@2.6.1)))(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2)(vitest@4.1.2(@types/node@25.5.0)(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))) + '@antfu/eslint-config': 7.7.3(@next/eslint-plugin-next@16.2.1)(@typescript-eslint/rule-tester@8.56.1(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(@typescript-eslint/typescript-estree@8.57.2(typescript@6.0.2))(@typescript-eslint/utils@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(@unocss/eslint-plugin@66.6.7(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(@vue/compiler-sfc@3.5.26)(eslint-plugin-format@2.0.1(eslint@10.1.0(jiti@2.6.1)))(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2)(vitest@4.1.2(@types/node@25.5.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))) '@eslint/js': 10.0.1(eslint@10.1.0(jiti@2.6.1)) '@next/eslint-plugin-next': 16.2.1 '@unocss/eslint-config': 66.6.7(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2) @@ -7807,22 +7838,22 @@ snapshots: path-browserify: 1.0.1 tinyglobby: 0.2.15 - '@turbo/darwin-64@2.8.20': + '@turbo/darwin-64@2.8.21': optional: true - '@turbo/darwin-arm64@2.8.20': + '@turbo/darwin-arm64@2.8.21': optional: true - '@turbo/linux-64@2.8.20': + '@turbo/linux-64@2.8.21': optional: true - '@turbo/linux-arm64@2.8.20': + '@turbo/linux-arm64@2.8.21': optional: true - '@turbo/windows-64@2.8.20': + '@turbo/windows-64@2.8.21': optional: true - '@turbo/windows-arm64@2.8.20': + '@turbo/windows-arm64@2.8.21': optional: true '@tybys/wasm-util@0.10.1': @@ -8239,12 +8270,12 @@ snapshots: d3-selection: 3.0.0 d3-transition: 3.0.1(d3-selection@3.0.0) - '@vitejs/plugin-react@6.0.1(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))': + '@vitejs/plugin-react@6.0.1(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@rolldown/pluginutils': 1.0.0-rc.7 - vite: 8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) - '@vitest/coverage-v8@4.1.2(vitest@4.1.2(@types/node@25.5.0)(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)))': + '@vitest/coverage-v8@4.1.2(vitest@4.1.2(@types/node@25.5.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: '@bcoe/v8-coverage': 1.0.2 '@vitest/utils': 4.1.2 @@ -8256,9 +8287,9 @@ snapshots: obug: 2.1.1 std-env: 4.0.0 tinyrainbow: 3.1.0 - vitest: 4.1.2(@types/node@25.5.0)(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.2(@types/node@25.5.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) - '@vitest/eslint-plugin@1.6.13(@typescript-eslint/eslint-plugin@8.57.2(@typescript-eslint/parser@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2)(vitest@4.1.2(@types/node@25.5.0)(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)))': + '@vitest/eslint-plugin@1.6.13(@typescript-eslint/eslint-plugin@8.57.2(@typescript-eslint/parser@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2)(vitest@4.1.2(@types/node@25.5.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)))': dependencies: '@typescript-eslint/scope-manager': 8.57.2 '@typescript-eslint/utils': 8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2) @@ -8266,7 +8297,7 @@ snapshots: optionalDependencies: '@typescript-eslint/eslint-plugin': 8.57.2(@typescript-eslint/parser@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2))(eslint@10.1.0(jiti@2.6.1))(typescript@6.0.2) typescript: 6.0.2 - vitest: 4.1.2(@types/node@25.5.0)(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) + vitest: 4.1.2(@types/node@25.5.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) transitivePeerDependencies: - supports-color @@ -8279,13 +8310,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.2(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))': + '@vitest/mocker@4.1.2(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 4.1.2 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) '@vitest/pretty-format@4.1.2': dependencies: @@ -8446,7 +8477,7 @@ snapshots: balanced-match@4.0.4: {} - baseline-browser-mapping@2.10.11: {} + baseline-browser-mapping@2.10.12: {} before-after-hook@4.0.0: {} @@ -8485,7 +8516,7 @@ snapshots: browserslist@4.28.1: dependencies: - baseline-browser-mapping: 2.10.11 + baseline-browser-mapping: 2.10.12 caniuse-lite: 1.0.30001781 electron-to-chromium: 1.5.328 node-releases: 2.0.36 @@ -8597,6 +8628,8 @@ snapshots: comment-parser@1.4.5: {} + comment-parser@1.4.6: {} + compute-scroll-into-view@3.1.1: {} confbox@0.1.8: {} @@ -9131,7 +9164,7 @@ snapshots: dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@10.1.0(jiti@2.6.1)) '@eslint-community/regexpp': 4.12.2 - comment-parser: 1.4.5 + comment-parser: 1.4.6 eslint: 10.1.0(jiti@2.6.1) jsdoc-type-pratt-parser: 7.1.1 refa: 0.12.1 @@ -10567,7 +10600,7 @@ snapshots: dependencies: '@next/env': 16.2.1 '@swc/helpers': 0.5.15 - baseline-browser-mapping: 2.10.11 + baseline-browser-mapping: 2.10.12 caniuse-lite: 1.0.30001781 postcss: 8.4.31 react: 19.2.4 @@ -11183,7 +11216,7 @@ snapshots: robust-predicates@3.0.3: {} - rolldown-plugin-dts@0.23.1(rolldown@1.0.0-rc.12)(typescript@6.0.2): + rolldown-plugin-dts@0.23.2(rolldown@1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1))(typescript@6.0.2): dependencies: '@babel/generator': 8.0.0-rc.3 '@babel/helper-validator-identifier': 8.0.0-rc.3 @@ -11194,13 +11227,14 @@ snapshots: dts-resolver: 2.1.3 get-tsconfig: 4.13.7 obug: 2.1.1 - rolldown: 1.0.0-rc.12 + picomatch: 4.0.4 + rolldown: 1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1) optionalDependencies: typescript: 6.0.2 transitivePeerDependencies: - oxc-resolver - rolldown@1.0.0-rc.12: + rolldown@1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1): dependencies: '@oxc-project/types': 0.122.0 '@rolldown/pluginutils': 1.0.0-rc.12 @@ -11217,9 +11251,12 @@ snapshots: '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.12 '@rolldown/binding-linux-x64-musl': 1.0.0-rc.12 '@rolldown/binding-openharmony-arm64': 1.0.0-rc.12 - '@rolldown/binding-wasm32-wasi': 1.0.0-rc.12 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1) '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.12 '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.12 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' roughjs@4.6.6: dependencies: @@ -11522,7 +11559,7 @@ snapshots: '@ts-morph/common': 0.28.1 code-block-writer: 13.0.3 - tsdown@0.21.6(synckit@0.11.12)(typescript@6.0.2): + tsdown@0.21.7(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(synckit@0.11.12)(typescript@6.0.2): dependencies: ansis: 4.2.0 cac: 7.0.0 @@ -11532,17 +11569,19 @@ snapshots: import-without-cache: 0.2.5 obug: 2.1.1 picomatch: 4.0.4 - rolldown: 1.0.0-rc.12 - rolldown-plugin-dts: 0.23.1(rolldown@1.0.0-rc.12)(typescript@6.0.2) + rolldown: 1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1) + rolldown-plugin-dts: 0.23.2(rolldown@1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1))(typescript@6.0.2) semver: 7.7.4 tinyexec: 1.0.4 tinyglobby: 0.2.15 tree-kill: 1.2.2 unconfig-core: 7.5.0 - unrun: 0.2.34(synckit@0.11.12) + unrun: 0.2.34(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(synckit@0.11.12) optionalDependencies: typescript: 6.0.2 transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' - '@ts-macro/tsc' - '@typescript/native-preview' - oxc-resolver @@ -11558,14 +11597,14 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - turbo@2.8.20: + turbo@2.8.21: optionalDependencies: - '@turbo/darwin-64': 2.8.20 - '@turbo/darwin-arm64': 2.8.20 - '@turbo/linux-64': 2.8.20 - '@turbo/linux-arm64': 2.8.20 - '@turbo/windows-64': 2.8.20 - '@turbo/windows-arm64': 2.8.20 + '@turbo/darwin-64': 2.8.21 + '@turbo/darwin-arm64': 2.8.21 + '@turbo/linux-64': 2.8.21 + '@turbo/linux-arm64': 2.8.21 + '@turbo/windows-64': 2.8.21 + '@turbo/windows-arm64': 2.8.21 tw-animate-css@1.4.0: {} @@ -11696,11 +11735,14 @@ snapshots: picomatch: 4.0.4 webpack-virtual-modules: 0.6.2 - unrun@0.2.34(synckit@0.11.12): + unrun@0.2.34(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(synckit@0.11.12): dependencies: - rolldown: 1.0.0-rc.12 + rolldown: 1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1) optionalDependencies: synckit: 0.11.12 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' update-browserslist-db@1.2.3(browserslist@4.28.1): dependencies: @@ -11754,12 +11796,12 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3): + vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 postcss: 8.5.8 - rolldown: 1.0.0-rc.12 + rolldown: 1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1) tinyglobby: 0.2.15 optionalDependencies: '@types/node': 25.5.0 @@ -11768,11 +11810,14 @@ snapshots: jiti: 2.6.1 tsx: 4.21.0 yaml: 2.8.3 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' - vitest@4.1.2(@types/node@25.5.0)(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)): + vitest@4.1.2(@types/node@25.5.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@vitest/expect': 4.1.2 - '@vitest/mocker': 4.1.2(vite@8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/mocker': 4.1.2(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) '@vitest/pretty-format': 4.1.2 '@vitest/runner': 4.1.2 '@vitest/snapshot': 4.1.2 @@ -11789,7 +11834,7 @@ snapshots: tinyexec: 1.0.4 tinyglobby: 0.2.15 tinyrainbow: 3.1.0 - vite: 8.0.3(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 25.5.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 1330eee..f11b11b 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -15,13 +15,13 @@ catalog: '@mdx-js/react': ^3.1.1 '@modelcontextprotocol/sdk': ^1.28.0 '@monaco-editor/react': ^4.7.0 - '@napi-rs/cli': ^3.5.1 + '@napi-rs/cli': ^3.6.0 '@next/eslint-plugin-next': ^16.2.1 '@next/mdx': ^16.2.0 '@tailwindcss/vite': ^4.2.2 - '@tanstack/react-router': ^1.168.7 - '@tanstack/router-generator': ^1.166.21 - '@tanstack/router-plugin': ^1.167.8 + '@tanstack/react-router': ^1.168.8 + '@tanstack/router-generator': ^1.166.22 + '@tanstack/router-plugin': ^1.167.9 '@tauri-apps/api': ^2.10.1 '@tauri-apps/cli': ^2.10.1 '@tauri-apps/plugin-shell': ^2.3.5 @@ -76,9 +76,9 @@ catalog: remark-stringify: ^11.0.0 tailwind-merge: ^3.5.0 tailwindcss: ^4.2.2 - tsdown: ^0.21.6 + tsdown: ^0.21.7 tsx: ^4.21.0 - turbo: ^2.8.20 + turbo: ^2.8.21 tw-animate-css: ^1.4.0 typescript: 6.0.2 typescript-eslint: ^8.57.2