@steipete/oracle 1.0.1 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,13 +24,16 @@ If you omit `--engine`, Oracle prefers the API engine when `OPENAI_API_KEY` is p
24
24
 
25
25
  ```bash
26
26
  # One-off (no install)
27
- OPENAI_API_KEY=sk-... npx @steipete/oracle -p "Summarize the risk register" --file docs/risk-register.md docs/risk-matrix.md
27
+ OPENAI_API_KEY=sk-... npx -y @steipete/oracle -p "Summarize the risk register" --file docs/risk-register.md docs/risk-matrix.md
28
28
 
29
29
  # Browser engine (no API key)
30
- npx @steipete/oracle --engine browser -p "Summarize the risk register" --file docs/risk-register.md docs/risk-matrix.md
30
+ npx -y @steipete/oracle --engine browser -p "Summarize the risk register" --file docs/risk-register.md docs/risk-matrix.md
31
31
 
32
32
  # Globs/exclusions
33
- npx @steipete/oracle -p "Review the TS data layer" --file "src/**/*.ts" --file "!src/**/*.test.ts"
33
+ npx -y @steipete/oracle -p "Review the TS data layer" --file "src/**/*.ts" --file "!src/**/*.test.ts"
34
+
35
+ # Mixed glob + single file
36
+ npx -y @steipete/oracle -p "Audit data layer" --file "src/**/*.ts" --file README.md
34
37
 
35
38
  # Inspect past sessions
36
39
  oracle status --clear --hours 168 # prune a week of cached runs
@@ -40,7 +43,7 @@ oracle session <id> # replay a run locally
40
43
 
41
44
  ## How do I integrate this?
42
45
 
43
- - **One-liner in CI** — `OPENAI_API_KEY=sk-... npx @steipete/oracle --prompt "Smoke-check latest PR" --file src/ docs/ --preview summary` (add to your pipeline as a non-blocking report step).
46
+ - **One-liner in CI** — `OPENAI_API_KEY=sk-... npx -y @steipete/oracle --prompt "Smoke-check latest PR" --file src/ docs/ --preview summary` (add to your pipeline as a non-blocking report step).
44
47
  - **Package script** — In `package.json`: `"oracle": "oracle --prompt \"Review the diff\" --file ."` then run `OPENAI_API_KEY=... pnpm oracle`.
45
48
 
46
49
  ## Highlights
@@ -33,6 +33,11 @@ program.hook('preAction', (thisCommand) => {
33
33
  return;
34
34
  }
35
35
  const opts = thisCommand.optsWithGlobals();
36
+ const positional = thisCommand.args?.[0];
37
+ if (!opts.prompt && positional) {
38
+ opts.prompt = positional;
39
+ thisCommand.setOptionValue('prompt', positional);
40
+ }
36
41
  if (shouldRequirePrompt(rawCliArgs, opts)) {
37
42
  throw new Error('Prompt is required. Provide it via --prompt "<text>".');
38
43
  }
@@ -41,6 +46,7 @@ program
41
46
  .name('oracle')
42
47
  .description('One-shot GPT-5 Pro / GPT-5.1 tool for hard questions that benefit from large file context and server-side search.')
43
48
  .version(VERSION)
49
+ .argument('[prompt]', 'Prompt text (shorthand for --prompt).')
44
50
  .option('-p, --prompt <text>', 'User prompt to send to the model.')
45
51
  .option('-f, --file <paths...>', 'Files/directories or glob patterns to attach (prefix with !pattern to exclude). Files larger than 1 MB are rejected automatically.', collectPaths, [])
46
52
  .option('-s, --slug <words>', 'Custom session slug (3-5 words).')
@@ -9,7 +9,7 @@ export async function showStatus({ hours, includeAll, limit, showExamples = fals
9
9
  const { entries, truncated, total } = filterSessionsByRange(metas, { hours, includeAll, limit });
10
10
  const richTty = process.stdout.isTTY && chalk.level > 0;
11
11
  if (!entries.length) {
12
- console.log('No sessions found for the requested range.');
12
+ console.log(CLEANUP_TIP);
13
13
  if (showExamples) {
14
14
  printStatusExamples();
15
15
  }
@@ -26,6 +26,15 @@ const defaultWait = (ms) => new Promise((resolve) => {
26
26
  });
27
27
  export async function runOracle(options, deps = {}) {
28
28
  const { apiKey = options.apiKey ?? process.env.OPENAI_API_KEY, cwd = process.cwd(), fs: fsModule = createFsAdapter(fs), log = console.log, write = (text) => process.stdout.write(text), now = () => performance.now(), clientFactory = createDefaultClientFactory(), client, wait = defaultWait, } = deps;
29
+ const maskApiKey = (key) => {
30
+ if (!key)
31
+ return null;
32
+ if (key.length <= 8)
33
+ return `${key[0] ?? ''}***${key[key.length - 1] ?? ''}`;
34
+ const prefix = key.slice(0, 4);
35
+ const suffix = key.slice(-4);
36
+ return `${prefix}****${suffix}`;
37
+ };
29
38
  const logVerbose = (message) => {
30
39
  if (options.verbose) {
31
40
  log(dim(`[verbose] ${message}`));
@@ -38,6 +47,10 @@ export async function runOracle(options, deps = {}) {
38
47
  env: 'OPENAI_API_KEY',
39
48
  });
40
49
  }
50
+ const maskedKey = maskApiKey(apiKey);
51
+ if (maskedKey) {
52
+ log(dim(`Using OPENAI_API_KEY=${maskedKey}`));
53
+ }
41
54
  const modelConfig = MODEL_CONFIGS[options.model];
42
55
  if (!modelConfig) {
43
56
  throw new PromptValidationError(`Unsupported model "${options.model}". Choose one of: ${Object.keys(MODEL_CONFIGS).join(', ')}`, { model: options.model });
@@ -57,6 +70,9 @@ export async function runOracle(options, deps = {}) {
57
70
  }
58
71
  else {
59
72
  logVerbose('No files attached.');
73
+ if (!isPreview) {
74
+ log(dim('Tip: no files attached — Oracle works best with project context. Add files via --file path/to/code or docs.'));
75
+ }
60
76
  }
61
77
  const fileTokenInfo = getFileTokenStats(files, {
62
78
  cwd,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steipete/oracle",
3
- "version": "1.0.1",
3
+ "version": "1.0.5",
4
4
  "description": "CLI wrapper around OpenAI Responses API with GPT-5 Pro and GPT-5.1 high reasoning modes.",
5
5
  "type": "module",
6
6
  "main": "dist/bin/oracle-cli.js",