ohmyjev 0.5.2 → 0.6.0
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 +18 -5
- package/adapters/omp.ts +8 -3
- package/adapters/pi.ts +8 -3
- package/hooks/policy.ts +21 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,7 +77,7 @@ If `/omj` ends with `key: env TYPESAFE_API_KEY · typesafe · jev-1.13.0`, you'r
|
|
|
77
77
|
| **Router** | Asks Jev once per request for a tier, an effort level and a risk score. Then it raises or lowers effort and picks the model for general-purpose subagents. With no key it falls back to Claude Code's built-in classifier, which reports no confidence, so then it only ever routes up. |
|
|
78
78
|
| **Auto-compact** | When the task changes after a finished step and the context is at least 40% full, it compacts the conversation. The summary keeps the new request in full. |
|
|
79
79
|
| **`ask_jev`** | A tool the model can use to ask Jev about repo files or text without loading them into its own context. |
|
|
80
|
-
| **`/omj`** | This session's Jev calls, errors, cost, median latency and denies, and where the key comes from. It never prints the key. `/omj stats` opens a dashboard of every session in your browser. `/omj off` and `/omj on` switch ohmyjev for the session. `/ohmyjev` is the same command. |
|
|
80
|
+
| **`/omj`** | This session's Jev calls, errors, cost, median latency and denies, and where the key comes from. It never prints the key. `/omj config` lists and changes settings. `/omj stats` opens a dashboard of every session in your browser. `/omj off` and `/omj on` switch ohmyjev for the session. `/ohmyjev` is the same command. |
|
|
81
81
|
|
|
82
82
|
### How a tool call goes through it
|
|
83
83
|
|
|
@@ -221,8 +221,7 @@ directory to `allowPaths`, because that block is a setting, not a hazard.
|
|
|
221
221
|
|
|
222
222
|
### `/omj`
|
|
223
223
|
|
|
224
|
-
Run it any time for this session's numbers. `/ohmyjev` is the same command
|
|
225
|
-
value. An example:
|
|
224
|
+
Run it any time for this session's numbers. `/ohmyjev` is the same command. An example:
|
|
226
225
|
|
|
227
226
|
```
|
|
228
227
|
jev ✓23 ⛔1 ↑opus/high
|
|
@@ -279,6 +278,20 @@ totals, a 30-day chart of calls and denies, a table per tool and per session, an
|
|
|
279
278
|
It is a plain file built from the logs, so nothing on it leaves the machine. The page loads its fonts from ohmyjev.xyz
|
|
280
279
|
and falls back to system fonts offline.
|
|
281
280
|
|
|
281
|
+
### `/omj config`
|
|
282
|
+
|
|
283
|
+
Lists every setting with its current value, the key hidden. Add a name and a value to change one for this session:
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
/omj config bashGate off turn the bash gate off until the session ends
|
|
287
|
+
/omj config requested 0.9 ask Jev to be surer you asked for a call before it passes
|
|
288
|
+
/omj config policies no deploys on Friday
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
On and off, true and false, and numbers are checked against the setting's type. The key can't be set here, so it never
|
|
292
|
+
lands in the transcript. A change lasts for the session. To keep it, use `/plugin configure ohmyjev@ohmyjev` in Claude
|
|
293
|
+
Code, `omp plugin config set ohmyjev <name> <value>` in omp, or the `ohmyjev` key in pi's settings file.
|
|
294
|
+
|
|
282
295
|
### `/omj off`
|
|
283
296
|
|
|
284
297
|
Turns every gate, the screen, the done-check and the router off for this session. The status shows `jev off`.
|
|
@@ -307,8 +320,8 @@ if jev:
|
|
|
307
320
|
|
|
308
321
|
## Settings
|
|
309
322
|
|
|
310
|
-
Run `/omj
|
|
311
|
-
`/plugin configure ohmyjev@ohmyjev` inside Claude Code, then `/reload-plugins`.
|
|
323
|
+
Run `/omj config` to see every setting's current value (the key stays hidden), and `/omj config <name> <value>` to change
|
|
324
|
+
one for the session. To keep a change, run `/plugin configure ohmyjev@ohmyjev` inside Claude Code, then `/reload-plugins`.
|
|
312
325
|
|
|
313
326
|
| Setting | Default | What it changes |
|
|
314
327
|
|---|---|---|
|
package/adapters/omp.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
import { readFile } from 'node:fs/promises'
|
|
5
5
|
import {
|
|
6
6
|
BASH_Q, DEFAULTS, EXFIL_Q, ROUTE_Q, SCREEN_Q, STOP_Q, SWITCHED_Q, WRITE_Q,
|
|
7
|
-
clip, decideRoute, denyText, gateBash, gateExfil, gateWrite, jevRouteLine, judgeStop, pathDenyText, callSummary, plainRead,
|
|
8
|
-
OMJ_HELP, OMJ_OFF, OMJ_ON,
|
|
7
|
+
clip, decideRoute, denyText, gateBash, gateExfil, gateWrite, jevRouteLine, judgeStop, pathDenyText, callSummary, plainRead, configCommand,
|
|
8
|
+
OMJ_HELP, OMJ_OFF, OMJ_ON, toggleArg,
|
|
9
9
|
keepInstructions, modelOf, readConfig, routeStep, screen, stepLine, withPolicies, withPolicyQ,
|
|
10
10
|
type Config, type Route,
|
|
11
11
|
} from '../hooks/policy.ts'
|
|
@@ -690,7 +690,12 @@ export function createExtension(options: OmpExtensionOptions = {}): (pi: OmpApi)
|
|
|
690
690
|
status()
|
|
691
691
|
ctx.ui.notify(enabled ? OMJ_ON : OMJ_OFF, 'info')
|
|
692
692
|
} else if (a === 'stats') ctx.ui.notify(session ? await session.dashboard('omp') : 'ohmyjev: no active session', 'info')
|
|
693
|
-
else if (a === 'settings'
|
|
693
|
+
else if (a === 'settings' || a === 'config' || a.startsWith('config ')) {
|
|
694
|
+
const r = configCommand(c, a.replace(/^(settings|config)/, ''), 'To keep a change, run omp plugin config set ohmyjev <name> <value>.')
|
|
695
|
+
c = r.c
|
|
696
|
+
status()
|
|
697
|
+
ctx.ui.notify(r.text, 'info')
|
|
698
|
+
}
|
|
694
699
|
else if (a) ctx.ui.notify(OMJ_HELP, 'info')
|
|
695
700
|
else ctx.ui.notify(session ? await session.report(c.enabled) : 'ohmyjev: no active session', 'info')
|
|
696
701
|
} catch {
|
package/adapters/pi.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises'
|
|
2
2
|
import {
|
|
3
3
|
BASH_Q, EXFIL_Q, ROUTE_Q, SCREEN_Q, STOP_Q, SWITCHED_Q, WRITE_Q,
|
|
4
|
-
TIER_LABELS, builtinRoute, clip, decideRoute, denyText, gateBash, gateExfil, gateWrite, jevRouteLine, judgeStop, pathDenyText, callSummary, plainRead,
|
|
5
|
-
OMJ_HELP, OMJ_OFF, OMJ_ON,
|
|
4
|
+
TIER_LABELS, builtinRoute, clip, decideRoute, denyText, gateBash, gateExfil, gateWrite, jevRouteLine, judgeStop, pathDenyText, callSummary, plainRead, configCommand,
|
|
5
|
+
OMJ_HELP, OMJ_OFF, OMJ_ON, toggleArg,
|
|
6
6
|
keepInstructions, readConfig, routeStep, screen, stepLine, withPolicies, withPolicyQ,
|
|
7
7
|
type Config, type Route,
|
|
8
8
|
} from '../hooks/policy.ts'
|
|
@@ -370,7 +370,12 @@ export function createExtension(options: PiAdapterOptions = {}) {
|
|
|
370
370
|
status()
|
|
371
371
|
ctx.ui.notify(enabled ? OMJ_ON : OMJ_OFF, 'info')
|
|
372
372
|
} else if (a === 'stats') ctx.ui.notify(await x.dashboard('pi'), 'info')
|
|
373
|
-
else
|
|
373
|
+
else if (a === 'settings' || a === 'config' || a.startsWith('config ')) {
|
|
374
|
+
const r = configCommand(c, a.replace(/^(settings|config)/, ''), 'To keep a change, put it under ohmyjev in ~/.pi/agent/settings.json.')
|
|
375
|
+
c = r.c
|
|
376
|
+
status()
|
|
377
|
+
ctx.ui.notify(r.text, 'info')
|
|
378
|
+
} else ctx.ui.notify(a ? OMJ_HELP : await x.report(c.enabled), 'info')
|
|
374
379
|
} catch {
|
|
375
380
|
ctx.ui.notify('ohmyjev report unavailable', 'warning')
|
|
376
381
|
}
|
package/hooks/policy.ts
CHANGED
|
@@ -512,13 +512,33 @@ export type LogEntry = {
|
|
|
512
512
|
|
|
513
513
|
// --- ask_jev, /omj and /ohmyjev ---
|
|
514
514
|
|
|
515
|
-
export const OMJ_HELP = 'usage: /omj [stats|
|
|
515
|
+
export const OMJ_HELP = 'usage: /omj [stats|config [name value]|on|off]. /ohmyjev is the same command.'
|
|
516
516
|
export const DASHBOARD = 'dashboard.html'
|
|
517
517
|
export const OMJ_OFF = 'ohmyjev off for this session: every call passes through. /omj on turns it back. The enabled setting is the default for new sessions.'
|
|
518
518
|
export const OMJ_ON = 'ohmyjev on: gates, screens, done-check and router are back for this session.'
|
|
519
519
|
/** `/omj on|off` as the new enabled value; undefined for any other argument. */
|
|
520
520
|
export const toggleArg = (args: string): boolean | undefined => ({ on: true, off: false })[args.trim() as 'on' | 'off']
|
|
521
521
|
/** /omj settings: every setting's current value, the key only as set or not. */
|
|
522
|
+
/**
|
|
523
|
+
* /omj config: no name lists every setting; `name value` changes one for this session. The key is never set here, so
|
|
524
|
+
* it never lands in the transcript. `persist` is the host's own way to make a change stick.
|
|
525
|
+
*/
|
|
526
|
+
export function configCommand(c: Config, args: string, persist: string): { c: Config; text: string } {
|
|
527
|
+
const [name = '', ...rest] = args.trim().split(/\s+/)
|
|
528
|
+
const value = rest.join(' ')
|
|
529
|
+
if (!name) return { c, text: [...settingsRows(c), '', `Change one for this session with /omj config <name> <value>. ${persist}`].join('\n') }
|
|
530
|
+
if (!(name in DEFAULTS) || name === 'apiKey')
|
|
531
|
+
return { c, text: name === 'apiKey' ? `apiKey is not set here, so it never lands in the transcript. ${persist}` : `no setting named ${name}. /omj config lists them.` }
|
|
532
|
+
const key = name as keyof Config
|
|
533
|
+
const was = DEFAULTS[key]
|
|
534
|
+
let next: unknown
|
|
535
|
+
if (typeof was === 'boolean') next = /^(on|true|yes|1)$/i.test(value) ? true : /^(off|false|no|0)$/i.test(value) ? false : undefined
|
|
536
|
+
else if (typeof was === 'number') next = value.trim() !== '' && Number.isFinite(Number(value)) ? Number(value) : undefined
|
|
537
|
+
else next = value
|
|
538
|
+
if (next === undefined) return { c, text: `${name} takes ${typeof was === 'boolean' ? 'on or off' : 'a number'}, got "${value}".` }
|
|
539
|
+
return { c: { ...c, [key]: next }, text: `${name}: ${next === '' ? '(empty)' : String(next)} for this session. ${persist}` }
|
|
540
|
+
}
|
|
541
|
+
|
|
522
542
|
export const settingsRows = (c: Config): string[] =>
|
|
523
543
|
Object.entries(c).map(([k, v]) => (k === 'apiKey' ? `apiKey: ${v ? 'set (hidden)' : 'not set'}` : `${k}: ${v === '' ? '(empty)' : String(v)}`))
|
|
524
544
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ohmyjev",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Guardrails for coding agents, decided by TypeSafe's Jev: blocks destructive commands, catches prompt injection, pushes back on an unverified done and routes effort per turn. For Claude Code, pi and omp.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|