@oh-my-pi/omp-stats 18.8.9 → 18.9.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/CHANGELOG.md +6 -0
- package/build.ts +4 -0
- package/dist/client/favicon.ico +0 -0
- package/dist/client/index.html +1 -0
- package/dist/types/frustration.d.ts +17 -8
- package/package.json +4 -4
- package/src/client/favicon.ico +0 -0
- package/src/frustration.ts +5 -28
- package/src/prompts/judge/frustration.json +19 -0
package/CHANGELOG.md
CHANGED
package/build.ts
CHANGED
|
@@ -39,6 +39,7 @@ const indexHtml = `<!DOCTYPE html>
|
|
|
39
39
|
})();
|
|
40
40
|
</script>
|
|
41
41
|
<link rel="stylesheet" href="index.css">
|
|
42
|
+
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
|
42
43
|
</head>
|
|
43
44
|
<body>
|
|
44
45
|
<div id="root"></div>
|
|
@@ -46,6 +47,9 @@ const indexHtml = `<!DOCTYPE html>
|
|
|
46
47
|
</body>
|
|
47
48
|
</html>`;
|
|
48
49
|
|
|
50
|
+
// Static asset the bundler never emits; copied beside index.css so the on-disk client and the embedded archive both serve it.
|
|
51
|
+
await fs.copyFile("./src/client/favicon.ico", "./dist/client/favicon.ico");
|
|
52
|
+
|
|
49
53
|
await Bun.write("./dist/client/index.html", indexHtml);
|
|
50
54
|
|
|
51
55
|
console.log("Build complete");
|
|
Binary file
|
package/dist/client/index.html
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* using the judge the omp host registered through `startServer`. Standalone
|
|
17
17
|
* `omp-stats` has none and only shows the regex fallback.
|
|
18
18
|
*/
|
|
19
|
-
import
|
|
19
|
+
import { type Judge, type Model } from "@oh-my-pi/pi-ai";
|
|
20
20
|
import { type FrustrationModelRow } from "./db.js";
|
|
21
21
|
import type { FrustrationDashboardStats, FrustrationEstimate, FrustrationJobStatus, FrustrationModelStats } from "./shared-types.js";
|
|
22
22
|
/** Judge supplied by the omp host process; `primaryModel` prices the pre-run estimate. */
|
|
@@ -25,17 +25,26 @@ export interface StatsJudge extends Judge {
|
|
|
25
25
|
}
|
|
26
26
|
/** Lazily resolves the host judge on first estimate/run so `omp stats` startup stays fast. */
|
|
27
27
|
export type StatsJudgeProvider = () => Promise<StatsJudge>;
|
|
28
|
-
/** Where the user's annoyance is aimed. */
|
|
29
|
-
export type FrustrationTarget = "assistant" | "other" | "none";
|
|
30
28
|
/**
|
|
31
|
-
* The two questions asked about every prose text, in ONE judge request
|
|
29
|
+
* The two questions asked about every prose text, in ONE judge request:
|
|
30
|
+
* `annoyed` (four levels) and `target` (`assistant`, `other`, or `none`).
|
|
32
31
|
* The cost constants below were measured with exactly these strings; changing
|
|
33
32
|
* them invalidates both the estimate and every cached verdict's meaning.
|
|
34
33
|
*/
|
|
35
|
-
export declare const FRUSTRATION_QUESTIONS: {
|
|
36
|
-
annoyed:
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
export declare const FRUSTRATION_QUESTIONS: import("@oh-my-pi/pi-ai").QuestionsFor<{
|
|
35
|
+
annoyed: {
|
|
36
|
+
instructions: string;
|
|
37
|
+
criteria: string[];
|
|
38
|
+
};
|
|
39
|
+
target: {
|
|
40
|
+
instructions: string;
|
|
41
|
+
criteria: {
|
|
42
|
+
assistant: string;
|
|
43
|
+
other: string;
|
|
44
|
+
none: string;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
}>;
|
|
39
48
|
/** Register (or replace) the host judge. Called by `startServer`. */
|
|
40
49
|
export declare function setStatsJudgeProvider(provider: StatsJudgeProvider | undefined): void;
|
|
41
50
|
/** Snapshot of the current run's progress. */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/omp-stats",
|
|
4
|
-
"version": "18.
|
|
4
|
+
"version": "18.9.0",
|
|
5
5
|
"description": "Local observability dashboard for omp AI usage statistics",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": {
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
"fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@oh-my-pi/pi-ai": "18.
|
|
46
|
-
"@oh-my-pi/pi-catalog": "18.
|
|
47
|
-
"@oh-my-pi/pi-utils": "18.
|
|
45
|
+
"@oh-my-pi/pi-ai": "18.9.0",
|
|
46
|
+
"@oh-my-pi/pi-catalog": "18.9.0",
|
|
47
|
+
"@oh-my-pi/pi-utils": "18.9.0",
|
|
48
48
|
"lucide-react": "^1.24.0",
|
|
49
49
|
"react": "19.2.7",
|
|
50
50
|
"react-dom": "19.2.7"
|
|
Binary file
|
package/src/frustration.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* using the judge the omp host registered through `startServer`. Standalone
|
|
17
17
|
* `omp-stats` has none and only shows the regex fallback.
|
|
18
18
|
*/
|
|
19
|
-
import
|
|
19
|
+
import { type Judge, judgeQuestions, type Model } from "@oh-my-pi/pi-ai";
|
|
20
20
|
import { compareRevision, parseRevision } from "@oh-my-pi/pi-catalog/compat/revision";
|
|
21
21
|
import { classifyModel } from "@oh-my-pi/pi-catalog/compat/taxonomy";
|
|
22
22
|
import { logger } from "@oh-my-pi/pi-utils";
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
type PendingProse,
|
|
33
33
|
upsertFrustrationVerdicts,
|
|
34
34
|
} from "./db";
|
|
35
|
+
import questionFile from "./prompts/judge/frustration.json" with { type: "json" };
|
|
35
36
|
import type {
|
|
36
37
|
FrustrationDashboardStats,
|
|
37
38
|
FrustrationEstimate,
|
|
@@ -47,37 +48,13 @@ export interface StatsJudge extends Judge {
|
|
|
47
48
|
/** Lazily resolves the host judge on first estimate/run so `omp stats` startup stays fast. */
|
|
48
49
|
export type StatsJudgeProvider = () => Promise<StatsJudge>;
|
|
49
50
|
|
|
50
|
-
/** Where the user's annoyance is aimed. */
|
|
51
|
-
export type FrustrationTarget = "assistant" | "other" | "none";
|
|
52
|
-
|
|
53
51
|
/**
|
|
54
|
-
* The two questions asked about every prose text, in ONE judge request
|
|
52
|
+
* The two questions asked about every prose text, in ONE judge request:
|
|
53
|
+
* `annoyed` (four levels) and `target` (`assistant`, `other`, or `none`).
|
|
55
54
|
* The cost constants below were measured with exactly these strings; changing
|
|
56
55
|
* them invalidates both the estimate and every cached verdict's meaning.
|
|
57
56
|
*/
|
|
58
|
-
export const FRUSTRATION_QUESTIONS
|
|
59
|
-
annoyed: {
|
|
60
|
-
type: "score",
|
|
61
|
-
instructions:
|
|
62
|
-
"A user typed this message to an AI coding assistant (code blocks and markup were removed). Rate how frustrated or annoyed the user sounds. Judge tone and wording only (caps, swearing, 'again', 'why did you', 'stop', 'wtf', exasperation), not task difficulty. Plain instructions or questions are neutral.",
|
|
63
|
-
criteria: [
|
|
64
|
-
"neutral / no frustration",
|
|
65
|
-
"mild irritation or impatience",
|
|
66
|
-
"clearly annoyed or exasperated",
|
|
67
|
-
"angry, hostile, or swearing",
|
|
68
|
-
],
|
|
69
|
-
},
|
|
70
|
-
target: {
|
|
71
|
-
type: "choice",
|
|
72
|
-
instructions: "If the user sounds annoyed, what is the annoyance aimed at?",
|
|
73
|
-
criteria: {
|
|
74
|
-
assistant:
|
|
75
|
-
"the AI's own behavior in this session: what it did, wrote, ignored, repeated, took too long on, or misunderstood (incl. reacting to its output with 'wtf', 'no', 'stop', 'again', 'why did you')",
|
|
76
|
-
other: "build tools, third-party libraries/services, pre-existing code or tests, the user's own past design, other people, or general product/UX feedback about the thing being built",
|
|
77
|
-
none: "not annoyed: a plain question, instruction, design musing, or casual chat",
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
};
|
|
57
|
+
export const FRUSTRATION_QUESTIONS = judgeQuestions(questionFile);
|
|
81
58
|
|
|
82
59
|
/** Per-request input-token overhead of {@link FRUSTRATION_QUESTIONS}, measured on jev-1.13. */
|
|
83
60
|
const REQUEST_OVERHEAD_TOKENS = 561;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"annoyed": {
|
|
3
|
+
"instructions": "A user typed this message to an AI coding assistant (code blocks and markup were removed). Rate how frustrated or annoyed the user sounds. Judge tone and wording only (caps, swearing, 'again', 'why did you', 'stop', 'wtf', exasperation), not task difficulty. Plain instructions or questions are neutral.",
|
|
4
|
+
"criteria": [
|
|
5
|
+
"neutral / no frustration",
|
|
6
|
+
"mild irritation or impatience",
|
|
7
|
+
"clearly annoyed or exasperated",
|
|
8
|
+
"angry, hostile, or swearing"
|
|
9
|
+
]
|
|
10
|
+
},
|
|
11
|
+
"target": {
|
|
12
|
+
"instructions": "If the user sounds annoyed, what is the annoyance aimed at?",
|
|
13
|
+
"criteria": {
|
|
14
|
+
"assistant": "the AI's own behavior in this session: what it did, wrote, ignored, repeated, took too long on, or misunderstood (incl. reacting to its output with 'wtf', 'no', 'stop', 'again', 'why did you')",
|
|
15
|
+
"other": "build tools, third-party libraries/services, pre-existing code or tests, the user's own past design, other people, or general product/UX feedback about the thing being built",
|
|
16
|
+
"none": "not annoyed: a plain question, instruction, design musing, or casual chat"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|