🤖 refactor: remove oracle from nix-steipete-tools
What: - delete oracle package and plugin exports - remove oracle from tool update and skill sync pipelines - remove oracle mentions from README Why: - oracle is no longer part of the bundled toolchain - keep package/update surface aligned with active bundled plugins only Tests: - go test ./... (pass) - nix flake check --no-build (pass)
This commit is contained in:
parent
d5fc8e2b07
commit
7cd25c98bb
@ -30,7 +30,6 @@ These tools are essential for a capable openclaw instance - screen capture, came
|
||||
| [**poltergeist**](https://github.com/steipete/poltergeist) | Universal file watcher with auto-rebuild |
|
||||
| [**sag**](https://github.com/steipete/sag) | Command-line ElevenLabs TTS with mac-style flags |
|
||||
| [**imsg**](https://github.com/steipete/imsg) | iMessage/SMS CLI |
|
||||
| [**oracle**](https://github.com/steipete/oracle) | Bundle prompts + files for AI queries |
|
||||
|
||||
## Usage (as openclaw plugins)
|
||||
|
||||
@ -85,7 +84,7 @@ Tools track upstream GitHub releases directly (not Homebrew).
|
||||
go run ./cmd/update-tools
|
||||
```
|
||||
|
||||
Fetches latest release versions/URLs/hashes and updates the Nix expressions. Oracle uses pnpm and auto-derives its hash via build mismatch.
|
||||
Fetches latest release versions/URLs/hashes and updates the Nix expressions.
|
||||
|
||||
## CI
|
||||
|
||||
|
||||
@ -67,7 +67,6 @@ func main() {
|
||||
{"peekaboo", "skills/peekaboo"},
|
||||
{"sag", "skills/sag"},
|
||||
{"imsg", "skills/imsg"},
|
||||
{"oracle", "skills/oracle"},
|
||||
}
|
||||
|
||||
log.Printf("[sync-skills] cloning clawdbot main")
|
||||
|
||||
@ -140,85 +140,6 @@ func updateSummarize(repoRoot string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateOracle(repoRoot string) error {
|
||||
log.Printf("[update-tools] oracle")
|
||||
oracleFile := filepath.Join(repoRoot, "nix", "pkgs", "oracle.nix")
|
||||
orig, err := os.ReadFile(oracleFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rel, err := internal.LatestRelease("steipete/oracle")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
version := strings.TrimPrefix(rel.TagName, "v")
|
||||
var assetURL string
|
||||
for _, a := range rel.Assets {
|
||||
if matched, _ := regexp.MatchString(`oracle-[0-9.]+\.tgz`, a.Name); matched {
|
||||
assetURL = a.BrowserDownloadURL
|
||||
break
|
||||
}
|
||||
}
|
||||
if assetURL == "" {
|
||||
return fmt.Errorf("no asset matched for oracle")
|
||||
}
|
||||
assetHash, err := internal.PrefetchHash(assetURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
lockHash, err := internal.PrefetchGitHub("steipete", "oracle", rel.TagName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := internal.ReplaceOnce(oracleFile, regexp.MustCompile(`version = "[^"]+";`), fmt.Sprintf(`version = "%s";`, version)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := internal.ReplaceOnce(oracleFile, regexp.MustCompile(`url = "[^"]+";`), fmt.Sprintf(`url = "%s";`, assetURL)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := internal.ReplaceOnce(oracleFile, regexp.MustCompile(`hash = "sha256-[^"]+";`), fmt.Sprintf(`hash = "%s";`, assetHash)); err != nil {
|
||||
return err
|
||||
}
|
||||
lockRe := regexp.MustCompile(`(?s)lockSrc = fetchFromGitHub \{[^}]*hash = "sha256-[^"]+";`)
|
||||
if err := internal.ReplaceOnceFunc(oracleFile, lockRe, func(s string) string {
|
||||
out := regexp.MustCompile(`rev = "[^"]+";`).ReplaceAllString(s, fmt.Sprintf(`rev = "%s";`, rel.TagName))
|
||||
out = regexp.MustCompile(`hash = "sha256-[^"]+";`).ReplaceAllString(out, fmt.Sprintf(`hash = "%s";`, lockHash))
|
||||
return out
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
pnpmRe := regexp.MustCompile(`(?s)pnpmDeps.*hash = "sha256-[^"]+";`)
|
||||
if err := internal.ReplaceOnceFunc(oracleFile, pnpmRe, func(s string) string {
|
||||
return regexp.MustCompile(`hash = "sha256-[^"]+";`).ReplaceAllString(s, `hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";`)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("[update-tools] oracle: deriving pnpm hash")
|
||||
logText, buildErr := internal.NixBuildOracle()
|
||||
pnpmHash := internal.ExtractGotHash(logText)
|
||||
if pnpmHash == "" {
|
||||
// Restore original file so we don't leave a broken placeholder hash behind.
|
||||
_ = os.WriteFile(oracleFile, orig, 0644)
|
||||
// Surface some context in CI logs. This is usually a hash-mismatch line we failed to parse.
|
||||
lines := strings.Split(logText, "\n")
|
||||
start := 0
|
||||
if len(lines) > 200 {
|
||||
start = len(lines) - 200
|
||||
}
|
||||
log.Printf("[update-tools] oracle build output (last %d lines):\n%s", len(lines)-start, strings.Join(lines[start:], "\n"))
|
||||
return fmt.Errorf("oracle pnpm hash not found (build err: %v)", buildErr)
|
||||
}
|
||||
if err := internal.ReplaceOnceFunc(oracleFile, pnpmRe, func(s string) string {
|
||||
return regexp.MustCompile(`hash = "sha256-[^"]+";`).ReplaceAllString(s, fmt.Sprintf(`hash = "%s";`, pnpmHash))
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
repoRoot, err := os.Getwd()
|
||||
if err != nil {
|
||||
@ -324,9 +245,4 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
if err := updateOracle(repoRoot); err != nil {
|
||||
// Oracle releases occasionally ship with an out-of-date pnpm-lock.yaml.
|
||||
// In that case, we keep the previously pinned version and still update other tools.
|
||||
log.Printf("[update-tools] skipping oracle update: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,6 @@
|
||||
poltergeist = [ "aarch64-darwin" ];
|
||||
sag = [ "aarch64-darwin" "x86_64-linux" ];
|
||||
imsg = [ "aarch64-darwin" ];
|
||||
oracle = [ "aarch64-darwin" "x86_64-linux" "aarch64-linux" ];
|
||||
};
|
||||
in {
|
||||
packages = forAllSystems (system:
|
||||
@ -63,12 +62,6 @@
|
||||
// (lib.optionalAttrs (supports "imsg") {
|
||||
imsg = pkgs.callPackage ./nix/pkgs/imsg.nix {};
|
||||
})
|
||||
// (lib.optionalAttrs (supports "oracle") {
|
||||
oracle = pkgs.callPackage ./nix/pkgs/oracle.nix {
|
||||
pkgs = pkgs;
|
||||
pnpm = if pkgs ? pnpm_10 then pkgs.pnpm_10 else pkgs.pnpm;
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
checks = forAllSystems (system: self.packages.${system});
|
||||
|
||||
@ -61,15 +61,6 @@ func PrefetchGitHub(owner, repo, rev string) (string, error) {
|
||||
return res.Hash, nil
|
||||
}
|
||||
|
||||
func NixBuildOracle() (string, error) {
|
||||
cmd := exec.Command("nix", "build", ".#oracle")
|
||||
var out bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
cmd.Stderr = &out
|
||||
err := cmd.Run()
|
||||
return out.String(), err
|
||||
}
|
||||
|
||||
func NixBuildSummarize() (string, error) {
|
||||
return NixBuildSummarizeSystem("")
|
||||
}
|
||||
|
||||
@ -1,128 +0,0 @@
|
||||
{ lib
|
||||
, stdenv
|
||||
, fetchurl
|
||||
, fetchFromGitHub
|
||||
, nodejs
|
||||
, pnpm
|
||||
, python3
|
||||
, python3Packages
|
||||
, pkg-config
|
||||
, makeWrapper
|
||||
, pkgs
|
||||
, zstd
|
||||
}:
|
||||
|
||||
let
|
||||
pnpmFetchDepsPkg = pkgs.callPackage "${pkgs.path}/pkgs/build-support/node/fetch-pnpm-deps" {
|
||||
inherit pnpm;
|
||||
};
|
||||
in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "oracle";
|
||||
version = "0.8.5";
|
||||
|
||||
srcTarball = fetchurl {
|
||||
url = "https://github.com/steipete/oracle/releases/download/v0.8.5/oracle-0.8.5.tgz";
|
||||
hash = "sha256-MSb1+5wEHK38iq+yob7Tz7xov0Wh9zHcmXGs/l2KdMA=";
|
||||
};
|
||||
|
||||
lockSrc = fetchFromGitHub {
|
||||
owner = "steipete";
|
||||
repo = "oracle";
|
||||
rev = "v0.8.5";
|
||||
hash = "sha256-q1l3IcVAj7Gb8Lp0JzQakLRg2AlVrJniMBHRwxKQVbM=";
|
||||
};
|
||||
|
||||
srcPatched = stdenv.mkDerivation {
|
||||
name = "oracle-src-patched";
|
||||
src = finalAttrs.srcTarball;
|
||||
nativeBuildInputs = [ python3 ];
|
||||
dontConfigure = true;
|
||||
dontBuild = true;
|
||||
unpackPhase = ''
|
||||
tar -xzf "$src"
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p "$out"
|
||||
if [ -d package ]; then
|
||||
shopt -s dotglob
|
||||
mv package/* "$out"/
|
||||
else
|
||||
cp -R . "$out"/
|
||||
fi
|
||||
cp -f "${finalAttrs.lockSrc}/pnpm-lock.yaml" "$out/pnpm-lock.yaml"
|
||||
export OUT_DIR="$out"
|
||||
python3 - <<'PY'
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
path = Path(os.environ["OUT_DIR"]) / "package.json"
|
||||
data = json.loads(path.read_text())
|
||||
data.pop("packageManager", None)
|
||||
path.write_text(json.dumps(data, indent=2) + "\n")
|
||||
PY
|
||||
'';
|
||||
};
|
||||
|
||||
src = finalAttrs.srcPatched;
|
||||
|
||||
pnpmDeps = (pnpmFetchDepsPkg.fetchPnpmDeps {
|
||||
pname = finalAttrs.pname;
|
||||
version = finalAttrs.version;
|
||||
src = finalAttrs.srcPatched;
|
||||
hash = "sha256-Tmwe55l4QMzXsO7F1kUSnGuZjkuMtDORNtqKnWZ/HrA=";
|
||||
fetcherVersion = 3;
|
||||
});
|
||||
|
||||
nativeBuildInputs = [
|
||||
nodejs
|
||||
pnpm
|
||||
python3
|
||||
python3Packages.setuptools
|
||||
pkg-config
|
||||
makeWrapper
|
||||
zstd
|
||||
];
|
||||
|
||||
env = {
|
||||
PNPM_IGNORE_PACKAGE_MANAGER_CHECK = "1";
|
||||
CI = "1";
|
||||
HOME = "/tmp";
|
||||
PNPM_HOME = "/tmp/pnpm-home";
|
||||
PNPM_CONFIG_HOME = "/tmp/pnpm-config";
|
||||
XDG_CACHE_HOME = "/tmp/pnpm-cache";
|
||||
NPM_CONFIG_USERCONFIG = "/tmp/pnpm-config/.npmrc";
|
||||
npm_config_nodedir = "${nodejs.dev}";
|
||||
npm_config_build_from_source = "1";
|
||||
PNPM_CONFIG_IGNORE_SCRIPTS = "1";
|
||||
};
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
mkdir -p "$HOME" "$PNPM_HOME" "$PNPM_CONFIG_HOME" "$XDG_CACHE_HOME"
|
||||
export PNPM_STORE_PATH="$TMPDIR/pnpm-store"
|
||||
mkdir -p "$PNPM_STORE_PATH"
|
||||
tar --zstd -xf ${finalAttrs.pnpmDeps}/pnpm-store.tar.zst -C "$PNPM_STORE_PATH"
|
||||
pnpm install --offline --no-frozen-lockfile --store-dir "$PNPM_STORE_PATH" --ignore-scripts
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p "$out/libexec" "$out/bin"
|
||||
cp -r dist package.json vendor assets-oracle-icon.png node_modules "$out/libexec/"
|
||||
chmod 0755 "$out/libexec/dist/bin/oracle-cli.js" "$out/libexec/dist/bin/oracle-mcp.js"
|
||||
ln -s "$out/libexec/dist/bin/oracle-cli.js" "$out/bin/oracle"
|
||||
ln -s "$out/libexec/dist/bin/oracle-mcp.js" "$out/bin/oracle-mcp"
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Bundle prompts + files for second-model review";
|
||||
homepage = "https://github.com/steipete/oracle";
|
||||
license = licenses.mit;
|
||||
platforms = [ "aarch64-darwin" "x86_64-linux" "aarch64-linux" ];
|
||||
mainProgram = "oracle";
|
||||
};
|
||||
})
|
||||
@ -1,38 +0,0 @@
|
||||
{
|
||||
description = "openclaw plugin: oracle";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs?rev=16c7794d0a28b5a37904d55bcca36003b9109aaa&narHash=sha256-fFUnEYMla8b7UKjijLnMe%2BoVFOz6HjijGGNS1l7dYaQ%3D";
|
||||
root.url = "github:openclaw/nix-steipete-tools?rev=dbf0a31a57407d9140e32357ea8d0215bd9feed9&narHash=sha256-QkPl/Rgk9DXgaVNhjvHHHjy5e81j+MzcVOouZRdUTLA=";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, root }:
|
||||
let
|
||||
lib = nixpkgs.lib;
|
||||
systems = builtins.attrNames root.packages;
|
||||
pluginFor = system:
|
||||
let
|
||||
packagesForSystem = root.packages.${system} or {};
|
||||
oracle = packagesForSystem.oracle or null;
|
||||
in
|
||||
if oracle == null then null else {
|
||||
name = "oracle";
|
||||
skills = [ ./skills/oracle ];
|
||||
packages = [ oracle ];
|
||||
needs = {
|
||||
stateDirs = [];
|
||||
requiredEnv = [];
|
||||
};
|
||||
};
|
||||
in {
|
||||
packages = lib.genAttrs systems (system:
|
||||
let
|
||||
oracle = (root.packages.${system} or {}).oracle or null;
|
||||
in
|
||||
if oracle == null then {}
|
||||
else { oracle = oracle; }
|
||||
);
|
||||
|
||||
openclawPlugin = pluginFor;
|
||||
};
|
||||
}
|
||||
@ -1,125 +0,0 @@
|
||||
---
|
||||
name: oracle
|
||||
description: Best practices for using the oracle CLI (prompt + file bundling, engines, sessions, and file attachment patterns).
|
||||
homepage: https://askoracle.dev
|
||||
metadata:
|
||||
{
|
||||
"openclaw":
|
||||
{
|
||||
"emoji": "🧿",
|
||||
"requires": { "bins": ["oracle"] },
|
||||
"install":
|
||||
[
|
||||
{
|
||||
"id": "node",
|
||||
"kind": "node",
|
||||
"package": "@steipete/oracle",
|
||||
"bins": ["oracle"],
|
||||
"label": "Install oracle (node)",
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
---
|
||||
|
||||
# oracle — best use
|
||||
|
||||
Oracle bundles your prompt + selected files into one “one-shot” request so another model can answer with real repo context (API or browser automation). Treat output as advisory: verify against code + tests.
|
||||
|
||||
## Main use case (browser, GPT‑5.2 Pro)
|
||||
|
||||
Default workflow here: `--engine browser` with GPT‑5.2 Pro in ChatGPT. This is the common “long think” path: ~10 minutes to ~1 hour is normal; expect a stored session you can reattach to.
|
||||
|
||||
Recommended defaults:
|
||||
|
||||
- Engine: browser (`--engine browser`)
|
||||
- Model: GPT‑5.2 Pro (`--model gpt-5.2-pro` or `--model "5.2 Pro"`)
|
||||
|
||||
## Golden path
|
||||
|
||||
1. Pick a tight file set (fewest files that still contain the truth).
|
||||
2. Preview payload + token spend (`--dry-run` + `--files-report`).
|
||||
3. Use browser mode for the usual GPT‑5.2 Pro workflow; use API only when you explicitly want it.
|
||||
4. If the run detaches/timeouts: reattach to the stored session (don’t re-run).
|
||||
|
||||
## Commands (preferred)
|
||||
|
||||
- Help:
|
||||
- `oracle --help`
|
||||
- If the binary isn’t installed: `npx -y @steipete/oracle --help` (avoid `pnpx` here; sqlite bindings).
|
||||
|
||||
- Preview (no tokens):
|
||||
- `oracle --dry-run summary -p "<task>" --file "src/**" --file "!**/*.test.*"`
|
||||
- `oracle --dry-run full -p "<task>" --file "src/**"`
|
||||
|
||||
- Token sanity:
|
||||
- `oracle --dry-run summary --files-report -p "<task>" --file "src/**"`
|
||||
|
||||
- Browser run (main path; long-running is normal):
|
||||
- `oracle --engine browser --model gpt-5.2-pro -p "<task>" --file "src/**"`
|
||||
|
||||
- Manual paste fallback:
|
||||
- `oracle --render --copy -p "<task>" --file "src/**"`
|
||||
- Note: `--copy` is a hidden alias for `--copy-markdown`.
|
||||
|
||||
## Attaching files (`--file`)
|
||||
|
||||
`--file` accepts files, directories, and globs. You can pass it multiple times; entries can be comma-separated.
|
||||
|
||||
- Include:
|
||||
- `--file "src/**"`
|
||||
- `--file src/index.ts`
|
||||
- `--file docs --file README.md`
|
||||
|
||||
- Exclude:
|
||||
- `--file "src/**" --file "!src/**/*.test.ts" --file "!**/*.snap"`
|
||||
|
||||
- Defaults (implementation behavior):
|
||||
- Default-ignored dirs: `node_modules`, `dist`, `coverage`, `.git`, `.turbo`, `.next`, `build`, `tmp` (skipped unless explicitly passed as literal dirs/files).
|
||||
- Honors `.gitignore` when expanding globs.
|
||||
- Does not follow symlinks.
|
||||
- Dotfiles filtered unless opted in via pattern (e.g. `--file ".github/**"`).
|
||||
- Files > 1 MB rejected.
|
||||
|
||||
## Engines (API vs browser)
|
||||
|
||||
- Auto-pick: `api` when `OPENAI_API_KEY` is set; otherwise `browser`.
|
||||
- Browser supports GPT + Gemini only; use `--engine api` for Claude/Grok/Codex or multi-model runs.
|
||||
- Browser attachments:
|
||||
- `--browser-attachments auto|never|always` (auto pastes inline up to ~60k chars then uploads).
|
||||
- Remote browser host:
|
||||
- Host: `oracle serve --host 0.0.0.0 --port 9473 --token <secret>`
|
||||
- Client: `oracle --engine browser --remote-host <host:port> --remote-token <secret> -p "<task>" --file "src/**"`
|
||||
|
||||
## Sessions + slugs
|
||||
|
||||
- Stored under `~/.oracle/sessions` (override with `ORACLE_HOME_DIR`).
|
||||
- Runs may detach or take a long time (browser + GPT‑5.2 Pro often does). If the CLI times out: don’t re-run; reattach.
|
||||
- List: `oracle status --hours 72`
|
||||
- Attach: `oracle session <id> --render`
|
||||
- Use `--slug "<3-5 words>"` to keep session IDs readable.
|
||||
- Duplicate prompt guard exists; use `--force` only when you truly want a fresh run.
|
||||
|
||||
## Prompt template (high signal)
|
||||
|
||||
Oracle starts with **zero** project knowledge. Assume the model cannot infer your stack, build tooling, conventions, or “obvious” paths. Include:
|
||||
|
||||
- Project briefing (stack + build/test commands + platform constraints).
|
||||
- “Where things live” (key directories, entrypoints, config files, boundaries).
|
||||
- Exact question + what you tried + the error text (verbatim).
|
||||
- Constraints (“don’t change X”, “must keep public API”, etc).
|
||||
- Desired output (“return patch plan + tests”, “give 3 options with tradeoffs”).
|
||||
|
||||
## Safety
|
||||
|
||||
- Don’t attach secrets by default (`.env`, key files, auth tokens). Redact aggressively; share only what’s required.
|
||||
|
||||
## “Exhaustive prompt” restoration pattern
|
||||
|
||||
For long investigations, write a standalone prompt + file set so you can rerun days later:
|
||||
|
||||
- 6–30 sentence project briefing + the goal.
|
||||
- Repro steps + exact errors + what you tried.
|
||||
- Attach all context files needed (entrypoints, configs, key modules, docs).
|
||||
|
||||
Oracle runs are one-shot; the model doesn’t remember prior runs. “Restoring context” means re-running with the same prompt + `--file …` set (or reattaching a still-running stored session).
|
||||
Loading…
Reference in New Issue
Block a user