refactor/remove-pi-agent-cleanup #14
@@ -1,117 +0,0 @@
|
||||
# notesmd-cli
|
||||
|
||||
Obsidian CLI (Community) - Interact with Obsidian in the terminal.
|
||||
|
||||
## Description
|
||||
|
||||
notesmd-cli is a command-line interface for interacting with Obsidian, the popular knowledge management and note-taking application. It allows you to create, search, and manipulate notes directly from the terminal.
|
||||
|
||||
## Features
|
||||
|
||||
- 📝 **Note Creation**: Create new notes from the command line
|
||||
- 🔍 **Search**: Search through your Obsidian vault
|
||||
- 📂 **Vault Management**: Interact with your vault structure
|
||||
- 🔗 **WikiLink Support**: Work with Obsidian's WikiLink format
|
||||
- 🏷️ **Tag Support**: Manage and search by tags
|
||||
- ⚡ **Fast**: Lightweight Go binary with no external dependencies
|
||||
|
||||
## Installation
|
||||
|
||||
### Via Overlay
|
||||
|
||||
```nix
|
||||
{pkgs, ...}: {
|
||||
environment.systemPackages = with pkgs; [
|
||||
notesmd-cli
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
### Direct Reference
|
||||
|
||||
```nix
|
||||
{pkgs, ...}: {
|
||||
environment.systemPackages = with pkgs; [
|
||||
inputs.m3ta-nixpkgs.packages.${pkgs.system}.notesmd-cli
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
### Run Directly
|
||||
|
||||
```bash
|
||||
nix run git+https://code.m3ta.dev/m3tam3re/nixpkgs#notesmd-cli
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Commands
|
||||
|
||||
```bash
|
||||
# Show help
|
||||
notesmd-cli --help
|
||||
|
||||
# Create a new note
|
||||
notesmd-cli new "My Note Title"
|
||||
|
||||
# Search notes
|
||||
notesmd-cli search "search term"
|
||||
|
||||
# List notes
|
||||
notesmd-cli list
|
||||
```
|
||||
|
||||
### Working with Vaults
|
||||
|
||||
```bash
|
||||
# Specify vault path
|
||||
notesmd-cli --vault /path/to/vault new "Note Title"
|
||||
|
||||
# Open a note in Obsidian
|
||||
notesmd-cli open "Note Name"
|
||||
```
|
||||
|
||||
### Advanced Usage
|
||||
|
||||
```bash
|
||||
# Search with tags
|
||||
notesmd-cli search --tag "project"
|
||||
|
||||
# Append to existing note
|
||||
notesmd-cli append "Note Name" "Additional content"
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
- `OBSIDIAN_VAULT`: Default vault path
|
||||
|
||||
### Command Line Options
|
||||
|
||||
Run `notesmd-cli --help` for a complete list of options.
|
||||
|
||||
## Build Information
|
||||
|
||||
- **Version**: 0.3.0
|
||||
- **Language**: Go
|
||||
- **License**: MIT
|
||||
- **Source**: [GitHub](https://github.com/Yakitrak/notesmd-cli)
|
||||
- **Vendor Hash**: null (no external dependencies)
|
||||
|
||||
## Platform Support
|
||||
|
||||
- Linux
|
||||
- macOS (Unix systems)
|
||||
|
||||
## Notes
|
||||
|
||||
- No vendor dependencies (pure Go stdlib)
|
||||
- The binary is named `notesmd-cli` (not `notesmd`)
|
||||
- This is the community CLI, not the official Obsidian CLI
|
||||
|
||||
## Related
|
||||
|
||||
- [Obsidian](https://obsidian.md) - The Obsidian application
|
||||
- [Adding Packages](../guides/adding-packages.md) - How to add new packages
|
||||
- [Quick Start](../QUICKSTART.md) - Getting started guide
|
||||
@@ -77,10 +77,7 @@
|
||||
};
|
||||
|
||||
# Library functions - helper utilities for your configuration
|
||||
lib = forAllSystems (system: let
|
||||
pkgs = pkgsFor system;
|
||||
in
|
||||
import ./lib {lib = pkgs.lib;});
|
||||
lib = forAllSystems (system: import ./lib {lib = nixpkgs.lib;});
|
||||
|
||||
# Development shells for various programming environments
|
||||
# Usage: nix develop .#<shell-name>
|
||||
@@ -104,6 +101,9 @@
|
||||
${pkgs.alejandra}/bin/alejandra --check ${./.}
|
||||
touch $out
|
||||
'';
|
||||
# Lib unit tests
|
||||
lib-agents = import ./tests/lib/agents-test.nix;
|
||||
lib-coding-rules = import ./tests/lib/coding-rules-test.nix;
|
||||
});
|
||||
|
||||
# Templates for creating new packages/modules
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Opencode rules management utilities
|
||||
# Coding rules management utilities
|
||||
#
|
||||
# This module provides functions to configure Opencode agent rules across
|
||||
# multiple projects. Rules are defined in the AGENTS repository and can be
|
||||
|
||||
@@ -3,76 +3,25 @@
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
}: let
|
||||
shared = import ./shared-options.nix {inherit lib;};
|
||||
in
|
||||
with lib; let
|
||||
cfg = config.coding.agents.claude-code;
|
||||
mcpCfg = config.programs.mcp or null;
|
||||
in {
|
||||
in {
|
||||
options.coding.agents.claude-code = {
|
||||
enable = mkEnableOption "Claude Code agent management via canonical agent.toml definitions";
|
||||
|
||||
agentsInput = mkOption {
|
||||
type = types.nullOr types.anything;
|
||||
default = null;
|
||||
description = ''
|
||||
agentsInput = shared.mkAgentsInputOption ''
|
||||
The `agents` flake input (your personal AGENTS repo).
|
||||
When set, agents are rendered from canonical agent.toml files
|
||||
and symlinked to ~/.claude/agents/.
|
||||
'';
|
||||
};
|
||||
|
||||
modelOverrides = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = {};
|
||||
description = ''
|
||||
Per-agent model overrides. Maps agent slug to model alias or ID.
|
||||
Example: { chiron = "claude-sonnet-4-20250514"; }
|
||||
'';
|
||||
example = literalExpression ''
|
||||
{
|
||||
chiron = "claude-sonnet-4-20250514";
|
||||
"chiron-forge" = "claude-sonnet-4-20250514";
|
||||
}
|
||||
'';
|
||||
};
|
||||
modelOverrides = shared.mkModelOverridesOption;
|
||||
|
||||
externalSkills = mkOption {
|
||||
type = types.listOf (types.submodule {
|
||||
options = {
|
||||
src = mkOption {
|
||||
type = types.anything;
|
||||
description = "Flake input pointing to a skills repository root.";
|
||||
};
|
||||
skillsDir = mkOption {
|
||||
type = types.str;
|
||||
default = "skills";
|
||||
description = ''
|
||||
Subdirectory inside src that contains skill folders.
|
||||
'';
|
||||
};
|
||||
selectSkills = mkOption {
|
||||
type = types.nullOr (types.listOf types.str);
|
||||
default = null;
|
||||
description = ''
|
||||
List of skill names to cherry-pick from this source.
|
||||
null means include every skill found in skillsDir.
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
default = [];
|
||||
description = ''
|
||||
External skill sources passed to mkOpencodeSkills.
|
||||
Each entry maps directly to an element of the externalSkills
|
||||
list accepted by the AGENTS flake's lib.mkOpencodeSkills.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
[
|
||||
{ src = inputs.skills-anthropic; selectSkills = [ "claude-api" ]; }
|
||||
{ src = inputs.skills-vercel; }
|
||||
]
|
||||
'';
|
||||
};
|
||||
externalSkills = shared.externalSkillsOption;
|
||||
|
||||
mcpServers = mkOption {
|
||||
type = types.attrsOf types.anything;
|
||||
@@ -128,13 +77,7 @@ in {
|
||||
source = cfg.agentsInput.lib.mkOpencodeSkills {
|
||||
inherit pkgs;
|
||||
customSkills = "${cfg.agentsInput}/skills";
|
||||
externalSkills =
|
||||
map (
|
||||
entry:
|
||||
{inherit (entry) src skillsDir;}
|
||||
// optionalAttrs (entry.selectSkills != null) {inherit (entry) selectSkills;}
|
||||
)
|
||||
cfg.externalSkills;
|
||||
externalSkills = shared.mapExternalSkills cfg.externalSkills;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -143,4 +86,4 @@ in {
|
||||
source = "${settingsJson}";
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,80 +3,30 @@
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.coding.agents.opencode;
|
||||
in {
|
||||
}: let
|
||||
shared = import ./shared-options.nix {inherit lib;};
|
||||
in
|
||||
with lib; {
|
||||
options.coding.agents.opencode = {
|
||||
enable = mkEnableOption "OpenCode agent management via canonical agent.toml definitions";
|
||||
|
||||
agentsInput = mkOption {
|
||||
type = types.nullOr types.anything;
|
||||
default = null;
|
||||
description = ''
|
||||
agentsInput = shared.mkAgentsInputOption ''
|
||||
The `agents` flake input (your personal AGENTS repo).
|
||||
When set, agents are rendered from canonical agent.toml files
|
||||
and symlinked to ~/.config/opencode/agents/.
|
||||
'';
|
||||
|
||||
modelOverrides = shared.mkModelOverridesOption;
|
||||
|
||||
externalSkills = shared.externalSkillsOption;
|
||||
};
|
||||
|
||||
modelOverrides = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = {};
|
||||
description = ''
|
||||
Per-agent model overrides. Maps agent slug to model string.
|
||||
Example: { chiron = "anthropic/claude-sonnet-4"; }
|
||||
'';
|
||||
example = literalExpression ''
|
||||
{
|
||||
chiron = "anthropic/claude-sonnet-4";
|
||||
"chiron-forge" = "anthropic/claude-sonnet-4";
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
externalSkills = mkOption {
|
||||
type = types.listOf (types.submodule {
|
||||
options = {
|
||||
src = mkOption {
|
||||
type = types.anything;
|
||||
description = "Flake input pointing to a skills repository root.";
|
||||
};
|
||||
skillsDir = mkOption {
|
||||
type = types.str;
|
||||
default = "skills";
|
||||
description = ''
|
||||
Subdirectory inside src that contains skill folders.
|
||||
'';
|
||||
};
|
||||
selectSkills = mkOption {
|
||||
type = types.nullOr (types.listOf types.str);
|
||||
default = null;
|
||||
description = ''
|
||||
List of skill names to cherry-pick from this source.
|
||||
null means include every skill found in skillsDir.
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
default = [];
|
||||
description = ''
|
||||
External skill sources passed to mkOpencodeSkills.
|
||||
Each entry maps directly to an element of the externalSkills
|
||||
list accepted by the AGENTS flake's lib.mkOpencodeSkills.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
[
|
||||
{ src = inputs.skills-anthropic; selectSkills = [ "claude-api" ]; }
|
||||
{ src = inputs.skills-vercel; }
|
||||
]
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = mkIf config.coding.agents.opencode.enable {
|
||||
# Rendered agent files symlinked to ~/.config/opencode/agents/
|
||||
xdg.configFile."opencode/agents" = mkIf (cfg.agentsInput != null) {
|
||||
xdg.configFile."opencode/agents" = let
|
||||
cfg = config.coding.agents.opencode;
|
||||
in
|
||||
mkIf (cfg.agentsInput != null) {
|
||||
source = (import ../../../../lib {inherit lib;}).agents.renderForOpencode {
|
||||
inherit pkgs;
|
||||
canonical = cfg.agentsInput.lib.loadAgents;
|
||||
@@ -85,29 +35,35 @@ in {
|
||||
};
|
||||
|
||||
# Skills (merged from personal AGENTS repo + optional external skills)
|
||||
xdg.configFile."opencode/skills" = mkIf (cfg.agentsInput != null) {
|
||||
xdg.configFile."opencode/skills" = let
|
||||
cfg = config.coding.agents.opencode;
|
||||
in
|
||||
mkIf (cfg.agentsInput != null) {
|
||||
source = cfg.agentsInput.lib.mkOpencodeSkills {
|
||||
inherit pkgs;
|
||||
customSkills = "${cfg.agentsInput}/skills";
|
||||
externalSkills =
|
||||
map (
|
||||
entry:
|
||||
{inherit (entry) src skillsDir;}
|
||||
// optionalAttrs (entry.selectSkills != null) {inherit (entry) selectSkills;}
|
||||
)
|
||||
cfg.externalSkills;
|
||||
externalSkills = shared.mapExternalSkills cfg.externalSkills;
|
||||
};
|
||||
};
|
||||
|
||||
# Static config dirs from AGENTS repo
|
||||
xdg.configFile."opencode/context" = mkIf (cfg.agentsInput != null) {
|
||||
xdg.configFile."opencode/context" = let
|
||||
cfg = config.coding.agents.opencode;
|
||||
in
|
||||
mkIf (cfg.agentsInput != null) {
|
||||
source = "${cfg.agentsInput}/context";
|
||||
};
|
||||
xdg.configFile."opencode/commands" = mkIf (cfg.agentsInput != null) {
|
||||
xdg.configFile."opencode/commands" = let
|
||||
cfg = config.coding.agents.opencode;
|
||||
in
|
||||
mkIf (cfg.agentsInput != null) {
|
||||
source = "${cfg.agentsInput}/commands";
|
||||
};
|
||||
xdg.configFile."opencode/prompts" = mkIf (cfg.agentsInput != null) {
|
||||
xdg.configFile."opencode/prompts" = let
|
||||
cfg = config.coding.agents.opencode;
|
||||
in
|
||||
mkIf (cfg.agentsInput != null) {
|
||||
source = "${cfg.agentsInput}/prompts";
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
}: let
|
||||
shared = import ./shared-options.nix {inherit lib;};
|
||||
in
|
||||
with lib; let
|
||||
cfg = config.coding.agents.pi;
|
||||
mcpCfg = config.programs.mcp or null;
|
||||
in {
|
||||
in {
|
||||
options.coding.agents.pi = {
|
||||
enable = mkEnableOption "Pi agent management via canonical agent.toml definitions";
|
||||
|
||||
@@ -22,25 +24,13 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
agentsInput = mkOption {
|
||||
type = types.nullOr types.anything;
|
||||
default = null;
|
||||
description = ''
|
||||
agentsInput = shared.mkAgentsInputOption ''
|
||||
The `agents` flake input (your personal AGENTS repo).
|
||||
When set, the primary agent's system prompt is rendered as SYSTEM.md,
|
||||
all agents are listed in AGENTS.md, and subagent .md files are deployed.
|
||||
'';
|
||||
};
|
||||
|
||||
modelOverrides = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = {};
|
||||
description = ''
|
||||
Per-agent model overrides for Pi subagents.
|
||||
Maps agent slug to model string, e.g.:
|
||||
{ chiron = "anthropic/claude-sonnet-4"; chiron-forge = "anthropic/claude-sonnet-4"; }
|
||||
'';
|
||||
};
|
||||
modelOverrides = shared.mkModelOverridesOption;
|
||||
|
||||
primaryAgent = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
@@ -51,43 +41,7 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
externalSkills = mkOption {
|
||||
type = types.listOf (types.submodule {
|
||||
options = {
|
||||
src = mkOption {
|
||||
type = types.anything;
|
||||
description = "Flake input pointing to a skills repository root.";
|
||||
};
|
||||
skillsDir = mkOption {
|
||||
type = types.str;
|
||||
default = "skills";
|
||||
description = ''
|
||||
Subdirectory inside src that contains skill folders.
|
||||
'';
|
||||
};
|
||||
selectSkills = mkOption {
|
||||
type = types.nullOr (types.listOf types.str);
|
||||
default = null;
|
||||
description = ''
|
||||
List of skill names to cherry-pick from this source.
|
||||
null means include every skill found in skillsDir.
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
default = [];
|
||||
description = ''
|
||||
External skill sources passed to mkOpencodeSkills.
|
||||
Each entry maps directly to an element of the externalSkills
|
||||
list accepted by the AGENTS flake's lib.mkOpencodeSkills.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
[
|
||||
{ src = inputs.skills-anthropic; selectSkills = [ "claude-api" ]; }
|
||||
{ src = inputs.basecamp; }
|
||||
]
|
||||
'';
|
||||
};
|
||||
externalSkills = shared.externalSkillsOption;
|
||||
|
||||
settings = mkOption {
|
||||
type = types.submodule {
|
||||
@@ -265,15 +219,9 @@ in {
|
||||
".pi/agent/skills".source = cfg.agentsInput.lib.mkOpencodeSkills {
|
||||
inherit pkgs;
|
||||
customSkills = "${cfg.agentsInput}/skills";
|
||||
externalSkills =
|
||||
map (
|
||||
entry:
|
||||
{inherit (entry) src skillsDir;}
|
||||
// optionalAttrs (entry.selectSkills != null) {inherit (entry) selectSkills;}
|
||||
)
|
||||
cfg.externalSkills;
|
||||
externalSkills = shared.mapExternalSkills cfg.externalSkills;
|
||||
};
|
||||
})
|
||||
];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
75
modules/home-manager/coding/agents/shared-options.nix
Normal file
75
modules/home-manager/coding/agents/shared-options.nix
Normal file
@@ -0,0 +1,75 @@
|
||||
# Shared option definitions for agent modules.
|
||||
# Prevents copy-pasting the externalSkills submodule across opencode/claude-code/pi.
|
||||
{lib}: let
|
||||
inherit (lib) mkOption mkEnableOption types literalExpression;
|
||||
in {
|
||||
# Common agentsInput option used by all agent modules.
|
||||
mkAgentsInputOption = description: mkOption {
|
||||
type = types.nullOr types.anything;
|
||||
default = null;
|
||||
inherit description;
|
||||
};
|
||||
|
||||
# Common modelOverrides option.
|
||||
mkModelOverridesOption = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = {};
|
||||
description = ''
|
||||
Per-agent model overrides. Maps agent slug to model string.
|
||||
Example: { chiron = "anthropic/claude-sonnet-4"; }
|
||||
'';
|
||||
example = literalExpression ''
|
||||
{
|
||||
chiron = "anthropic/claude-sonnet-4";
|
||||
"chiron-forge" = "anthropic/claude-sonnet-4";
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
# External skills submodule — used by opencode, claude-code, and pi modules.
|
||||
externalSkillsOption = mkOption {
|
||||
type = types.listOf (types.submodule {
|
||||
options = {
|
||||
src = mkOption {
|
||||
type = types.anything;
|
||||
description = "Flake input pointing to a skills repository root.";
|
||||
};
|
||||
skillsDir = mkOption {
|
||||
type = types.str;
|
||||
default = "skills";
|
||||
description = ''
|
||||
Subdirectory inside src that contains skill folders.
|
||||
'';
|
||||
};
|
||||
selectSkills = mkOption {
|
||||
type = types.nullOr (types.listOf types.str);
|
||||
default = null;
|
||||
description = ''
|
||||
List of skill names to cherry-pick from this source.
|
||||
null means include every skill found in skillsDir.
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
default = [];
|
||||
description = ''
|
||||
External skill sources passed to mkOpencodeSkills.
|
||||
Each entry maps directly to an element of the externalSkills
|
||||
list accepted by the AGENTS flake's lib.mkOpencodeSkills.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
[
|
||||
{ src = inputs.skills-anthropic; selectSkills = [ "claude-api" ]; }
|
||||
{ src = inputs.basecamp; }
|
||||
]
|
||||
'';
|
||||
};
|
||||
|
||||
# Helper to map externalSkills from module config to mkOpencodeSkills format.
|
||||
mapExternalSkills = cfgEntries:
|
||||
map (
|
||||
entry:
|
||||
{inherit (entry) src skillsDir;}
|
||||
// lib.optionalAttrs (entry.selectSkills != null) {inherit (entry) selectSkills;}
|
||||
) cfgEntries;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
{inputs, ...}: {
|
||||
# This one brings our custom packages from the 'pkgs' directory
|
||||
additions = final: prev: (import ../pkgs {pkgs = final;});
|
||||
|
||||
# This one contains whatever you want to overlay
|
||||
# You can change versions, add patches, set compilation flags, anything really.
|
||||
# https://nixos.wiki/wiki/Overlays
|
||||
modifications = final: prev:
|
||||
# Import all package modifications from mods directory
|
||||
(import ./mods/default.nix {inherit prev;})
|
||||
// {
|
||||
# Direct configuration overrides
|
||||
brave = prev.brave.override {
|
||||
commandLineArgs = "--password-store=gnome-libsecret";
|
||||
};
|
||||
};
|
||||
|
||||
master-packages = final: _prev: {
|
||||
master = import inputs.nixpkgs-master {
|
||||
system = final.stdenv.hostPlatform.system;
|
||||
config.allowUnfree = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
{prev}:
|
||||
prev.beads.overrideAttrs (oldAttrs: rec {
|
||||
version = "0.47.1";
|
||||
|
||||
src = prev.fetchFromGitHub {
|
||||
owner = "steveyegge";
|
||||
repo = "beads";
|
||||
tag = "v${version}";
|
||||
hash = "sha256-DwIR/r1TJnpVd/CT1E2OTkAjU7k9/KHbcVwg5zziFVg=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-pY5m5ODRgqghyELRwwxOr+xlW41gtJWLXaW53GlLaFw=";
|
||||
|
||||
# Tests require git worktree operations that fail in Nix sandbox
|
||||
doCheck = false;
|
||||
})
|
||||
@@ -1,18 +0,0 @@
|
||||
{prev}:
|
||||
prev.n8n.overrideAttrs (oldAttrs: rec {
|
||||
version = "2.4.1";
|
||||
|
||||
src = prev.fetchFromGitHub {
|
||||
owner = "n8n-io";
|
||||
repo = "n8n";
|
||||
rev = "n8n@${version}";
|
||||
hash = "sha256-EQP9ZI8kt30SUYE1+/UUpxQXpavzKqDu8qE24zsNifg=";
|
||||
};
|
||||
|
||||
pnpmDeps = prev.pnpm_10.fetchDeps {
|
||||
pname = oldAttrs.pname;
|
||||
inherit version src;
|
||||
fetcherVersion = 1;
|
||||
hash = "sha256-Q30IuFEQD3896Hg0HCLd38YE2i8fJn74JY0o95LKJis=";
|
||||
};
|
||||
})
|
||||
Reference in New Issue
Block a user