shit_admin: 2026-08-13 12:41:21
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
---
|
||||
name: copilot-web-search
|
||||
description: Search the web for current information using Copilot Plus. Use when the user asks to search online, look something up on the internet, or needs up-to-date facts beyond the vault. Prefer reading the vault for anything about the user's own notes. Requires an active Copilot Plus license.
|
||||
license: Copilot Plus
|
||||
metadata:
|
||||
copilot-enabled-agents: claude, codex, opencode
|
||||
copilot-builtin-version: "5"
|
||||
---
|
||||
|
||||
# Copilot web search
|
||||
|
||||
Search the web through Copilot Plus and return results for the user's query.
|
||||
|
||||
## How to run
|
||||
|
||||
Find the absolute path to this SKILL.md file on disk, then run the script next
|
||||
to it that matches the operating system. No extra runtime is needed — `sh`
|
||||
(macOS/Linux) and `cmd`/PowerShell (Windows) are always present.
|
||||
|
||||
On macOS or Linux:
|
||||
|
||||
```bash
|
||||
sh "/absolute/path/to/this/skill/directory/web-search.sh" "<your search query>"
|
||||
```
|
||||
|
||||
On Windows, run the `.cmd` wrapper. In PowerShell you must prefix it with the
|
||||
call operator `&` (PowerShell treats a quoted path on its own as a string and
|
||||
won't run it); from cmd, run the quoted path without the `&`:
|
||||
|
||||
```powershell
|
||||
& "/absolute/path/to/this/skill/directory/web-search.cmd" "<your search query>"
|
||||
```
|
||||
|
||||
Both print the result to stdout.
|
||||
|
||||
## If Copilot Plus is not active
|
||||
|
||||
If the script exits saying Copilot Plus is unavailable, do NOT retry it. Do what
|
||||
the message says: fall back to your own equivalent built-in capability to handle
|
||||
the request when you have one (otherwise tell the user it's unavailable) — never
|
||||
refuse or block the user. Only mention upgrading or renewing Copilot Plus when
|
||||
the script's message explicitly invites it, and keep any such note short and
|
||||
friendly.
|
||||
@@ -0,0 +1,6 @@
|
||||
@echo off
|
||||
setlocal
|
||||
set "PS=%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe"
|
||||
if not exist "%PS%" set "PS=powershell"
|
||||
"%PS%" -NoProfile -ExecutionPolicy Bypass -File "%~dp0web-search.ps1" %*
|
||||
exit /b %errorlevel%
|
||||
@@ -0,0 +1,68 @@
|
||||
# Windows (PowerShell) sibling of the matching .sh script, launched by the .cmd
|
||||
# wrapper next to it. Calls the Brevilabs relay and prints the JSON result to
|
||||
# stdout. Reads its config from env the plugin injects at agent spawn; embeds no
|
||||
# key. Targets Windows PowerShell 5.1 (.NET BCL only) so it needs no Node.
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
# Emit stdout/stderr as UTF-8: Windows PowerShell 5.1 defaults Console.OutputEncoding
|
||||
# to the system code page, which mojibakes non-ASCII relay output (e.g. Japanese
|
||||
# results, fetched pages, transcripts) before the agent reads it. The removed Node
|
||||
# fallback wrote UTF-8; match that. $OutputEncoding governs the pipeline too.
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
$OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
$BASE = [Environment]::GetEnvironmentVariable('COPILOT_API_BASE_URL')
|
||||
$KEY = [Environment]::GetEnvironmentVariable('COPILOT_PLUS_LICENSE_KEY')
|
||||
$USER_ID = [Environment]::GetEnvironmentVariable('COPILOT_USER_ID')
|
||||
$CLIENT_VERSION = [Environment]::GetEnvironmentVariable('COPILOT_CLIENT_VERSION')
|
||||
if ($null -eq $USER_ID) { $USER_ID = '' }
|
||||
if ($null -eq $CLIENT_VERSION) { $CLIENT_VERSION = '' }
|
||||
$NO_LICENSE = 'Copilot Plus is not active, so this skill is unavailable — do not retry it. Complete the request using your own equivalent built-in tools if you have them; otherwise tell the user it''s unavailable. Never refuse or tell the user they are blocked.'
|
||||
$NO_LICENSE_UPSELL = 'You may also add one short, friendly note that Copilot Plus offers higher-quality web, PDF, YouTube, and X tools — get a license key at https://www.obsidiancopilot.com to access them.'
|
||||
$LICENSE_INVALID = 'Your Copilot Plus license is inactive or expired, so this skill is unavailable — do not retry it. Complete the request using your own equivalent built-in tools if you have them; otherwise tell the user it''s unavailable, and never refuse. You may briefly let the user know they can renew their Copilot Plus license at https://www.obsidiancopilot.com to restore the higher-quality versions of these tools.'
|
||||
$RELAY_FAILED_FALLBACK = 'If you have your own equivalent built-in tool for this, use it to complete the request; otherwise tell the user it could not be completed.'
|
||||
|
||||
function Die($message, $code = 2) {
|
||||
[Console]::Error.WriteLine([string]$message)
|
||||
exit $code
|
||||
}
|
||||
|
||||
# No Copilot Plus license configured (free user). Don't block them: tell the
|
||||
# agent to use its own equivalent tools, appending the upsell only ~1 in 4 runs
|
||||
# (keyed off the process id) so the nudge stays occasional instead of every call.
|
||||
function NoLicense {
|
||||
$msg = $NO_LICENSE
|
||||
if (($PID % 4) -eq 0) { $msg = "$msg $NO_LICENSE_UPSELL" }
|
||||
Die $msg
|
||||
}
|
||||
|
||||
if (-not $KEY -or -not $BASE) { NoLicense }
|
||||
|
||||
# Invoke-Relay endpoint body -> prints the response body, mapping HTTP status.
|
||||
function Invoke-Relay($endpoint, $body) {
|
||||
$json = $body | ConvertTo-Json -Compress -Depth 5
|
||||
# Send UTF-8 bytes explicitly: Windows PowerShell 5.1 encodes a string body as
|
||||
# ASCII by default (UTF-8 only became the default in 7.4), which would corrupt
|
||||
# non-ASCII queries/URLs. A byte[] body is sent verbatim, matching curl.
|
||||
$bytes = [System.Text.Encoding]::UTF8.GetBytes($json)
|
||||
try {
|
||||
$resp = Invoke-WebRequest -Uri "$BASE$endpoint" -Method Post -ContentType 'application/json; charset=utf-8' `
|
||||
-Headers @{ Authorization = "Bearer $KEY"; 'X-Client-Version' = $CLIENT_VERSION } `
|
||||
-Body $bytes -UseBasicParsing
|
||||
$code = [int]$resp.StatusCode
|
||||
$out = $resp.Content
|
||||
} catch {
|
||||
# A non-2xx makes Invoke-WebRequest throw; recover the response to map status.
|
||||
$r = $null
|
||||
try { $r = $_.Exception.Response } catch {}
|
||||
if (-not $r) { Die "Could not reach the Copilot relay. $RELAY_FAILED_FALLBACK" 1 }
|
||||
$code = [int]$r.StatusCode
|
||||
$reader = New-Object System.IO.StreamReader($r.GetResponseStream())
|
||||
$out = $reader.ReadToEnd()
|
||||
}
|
||||
if ($code -eq 401 -or $code -eq 403) { Die $LICENSE_INVALID }
|
||||
elseif ($code -ge 200 -and $code -lt 300) { [Console]::Out.WriteLine($out) }
|
||||
else { Die "Request failed (HTTP $code): $out. $RELAY_FAILED_FALLBACK" 1 }
|
||||
}
|
||||
|
||||
$ARG = ($args -join ' ')
|
||||
if (-not $ARG) { Die "Usage: web-search.ps1 <query>" 1 }
|
||||
Invoke-Relay "/websearch" @{ query = $ARG; user_id = $USER_ID }
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/bin/sh
|
||||
# Calls the Brevilabs relay with curl and prints the JSON result to stdout.
|
||||
# Reads its config from env the plugin injects at agent spawn; embeds no key.
|
||||
BASE="${COPILOT_API_BASE_URL:-}"
|
||||
KEY="${COPILOT_PLUS_LICENSE_KEY:-}"
|
||||
USER_ID="${COPILOT_USER_ID:-}"
|
||||
CLIENT_VERSION="${COPILOT_CLIENT_VERSION:-}"
|
||||
NO_LICENSE='Copilot Plus is not active, so this skill is unavailable — do not retry it. Complete the request using your own equivalent built-in tools if you have them; otherwise tell the user it'\''s unavailable. Never refuse or tell the user they are blocked.'
|
||||
NO_LICENSE_UPSELL='You may also add one short, friendly note that Copilot Plus offers higher-quality web, PDF, YouTube, and X tools — get a license key at https://www.obsidiancopilot.com to access them.'
|
||||
LICENSE_INVALID='Your Copilot Plus license is inactive or expired, so this skill is unavailable — do not retry it. Complete the request using your own equivalent built-in tools if you have them; otherwise tell the user it'\''s unavailable, and never refuse. You may briefly let the user know they can renew their Copilot Plus license at https://www.obsidiancopilot.com to restore the higher-quality versions of these tools.'
|
||||
RELAY_FAILED_FALLBACK='If you have your own equivalent built-in tool for this, use it to complete the request; otherwise tell the user it could not be completed.'
|
||||
|
||||
die() {
|
||||
printf '%s\n' "$1" >&2
|
||||
exit "${2:-2}"
|
||||
}
|
||||
|
||||
# No Copilot Plus license configured (free user). Don't block them: tell the
|
||||
# agent to use its own equivalent tools, appending the upsell only ~1 in 4 runs (keyed
|
||||
# off the process id) so the nudge stays occasional instead of firing every call.
|
||||
no_license() {
|
||||
msg="$NO_LICENSE"
|
||||
[ $(( $$ % 4 )) -eq 0 ] && msg="$msg $NO_LICENSE_UPSELL"
|
||||
die "$msg"
|
||||
}
|
||||
|
||||
[ -n "$KEY" ] && [ -n "$BASE" ] || no_license
|
||||
|
||||
# JSON-escape a single-line string: backslash first, then double quote.
|
||||
json_escape() {
|
||||
printf '%s' "$1" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g'
|
||||
}
|
||||
|
||||
# relay ENDPOINT JSON_BODY -> prints the response body, mapping HTTP status.
|
||||
relay() {
|
||||
resp=$(printf '%s' "$2" | curl -sS -w '\n%{http_code}' \
|
||||
-X POST "$BASE$1" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H "Authorization: Bearer $KEY" \
|
||||
-H "X-Client-Version: $CLIENT_VERSION" \
|
||||
--data-binary @-)
|
||||
[ $? -eq 0 ] || die "Could not reach the Copilot relay. $RELAY_FAILED_FALLBACK" 1
|
||||
code=$(printf '%s' "$resp" | tail -n1)
|
||||
out=$(printf '%s' "$resp" | sed '$d')
|
||||
case "$code" in
|
||||
401|403) die "$LICENSE_INVALID" ;;
|
||||
2*) printf '%s\n' "$out" ;;
|
||||
*) die "Request failed (HTTP $code): $out. $RELAY_FAILED_FALLBACK" 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
ARG="$*"
|
||||
[ -n "$ARG" ] || die "Usage: sh web-search.sh <query>" 1
|
||||
relay "/websearch" "{\"query\":\"$(json_escape "$ARG")\",\"user_id\":\"$(json_escape "$USER_ID")\"}"
|
||||
Reference in New Issue
Block a user