ohmyjev 0.5.1 → 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 +29 -11
- 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
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
```
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
Y88b 888 d8b
|
|
3
|
+
Y88b 888 Y8P
|
|
4
|
+
Y88b 888
|
|
5
|
+
Y88b .d88b. 88888b. 88888b.d88b. 888 888 8888 .d88b. 888 888
|
|
6
|
+
d88P d88""88b 888 "88b 888 "888 "88b 888 888 "888 d8P Y8b 888 888
|
|
7
|
+
d88P 888 888 888 888 888 888 888 888 888 888 88888888 Y88 88P
|
|
8
|
+
d88P Y88..88P 888 888 888 888 888 Y88b 888 888 Y8b. Y8bd8P
|
|
9
|
+
d88P 88888888 "Y88P" 888 888 888 888 888 "Y88888 888 "Y8888 Y88P
|
|
10
|
+
888 888
|
|
11
|
+
Y8b d88P d88P
|
|
12
|
+
"Y88P" 888P"
|
|
8
13
|
```
|
|
9
14
|
|
|
10
15
|
<p align="center">
|
|
@@ -72,7 +77,7 @@ If `/omj` ends with `key: env TYPESAFE_API_KEY · typesafe · jev-1.13.0`, you'r
|
|
|
72
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. |
|
|
73
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. |
|
|
74
79
|
| **`ask_jev`** | A tool the model can use to ask Jev about repo files or text without loading them into its own context. |
|
|
75
|
-
| **`/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. |
|
|
76
81
|
|
|
77
82
|
### How a tool call goes through it
|
|
78
83
|
|
|
@@ -216,8 +221,7 @@ directory to `allowPaths`, because that block is a setting, not a hazard.
|
|
|
216
221
|
|
|
217
222
|
### `/omj`
|
|
218
223
|
|
|
219
|
-
Run it any time for this session's numbers. `/ohmyjev` is the same command
|
|
220
|
-
value. An example:
|
|
224
|
+
Run it any time for this session's numbers. `/ohmyjev` is the same command. An example:
|
|
221
225
|
|
|
222
226
|
```
|
|
223
227
|
jev ✓23 ⛔1 ↑opus/high
|
|
@@ -274,6 +278,20 @@ totals, a 30-day chart of calls and denies, a table per tool and per session, an
|
|
|
274
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
|
|
275
279
|
and falls back to system fonts offline.
|
|
276
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
|
+
|
|
277
295
|
### `/omj off`
|
|
278
296
|
|
|
279
297
|
Turns every gate, the screen, the done-check and the router off for this session. The status shows `jev off`.
|
|
@@ -302,8 +320,8 @@ if jev:
|
|
|
302
320
|
|
|
303
321
|
## Settings
|
|
304
322
|
|
|
305
|
-
Run `/omj
|
|
306
|
-
`/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`.
|
|
307
325
|
|
|
308
326
|
| Setting | Default | What it changes |
|
|
309
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",
|