@harny/sdk 0.0.1-alpha.1

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.
Files changed (3) hide show
  1. package/README.md +63 -0
  2. package/index.js +270 -0
  3. package/package.json +17 -0
package/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # @harny/sdk
2
+
3
+ **A scoring engine that rates your AI's vibes on a scale of 1–100. Harness engineering makes it HARNY.**
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @harny/sdk
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```js
14
+ const harny = require("@harny/sdk");
15
+
16
+ // Quick vibe check — no input needed
17
+ const result = harny.vibeCheck();
18
+ harny.print(result);
19
+
20
+ // Full evaluation
21
+ const result = harny.score({
22
+ prompt: "Explain quantum computing using interpretive dance metaphors",
23
+ reasoning: "Let me think step by step about how qubits are like dancers...",
24
+ result: "Imagine each qubit as a dancer spinning in superposition..."
25
+ });
26
+
27
+ console.log(result.score); // 73.42
28
+ console.log(result.reaction); // "my GPU is getting warm and it's not the cooling fan."
29
+ console.log(result.verdict); // "Dangerously Harny"
30
+ ```
31
+
32
+ ## What It Scores
33
+
34
+ All inputs are **optional**. Provide whatever you have:
35
+
36
+ | Input | What It Measures |
37
+ |-------|-----------------|
38
+ | `prompt` | The instruction given to the AI |
39
+ | `reasoning` | Chain-of-thought, scratchpad, reasoning traces |
40
+ | `result` | The AI's final output |
41
+
42
+ ## Score Guide
43
+
44
+ | Score | Verdict |
45
+ |-------|---------|
46
+ | 1–15 | Completely Unharny |
47
+ | 16–25 | Mildly Stale |
48
+ | 26–35 | Room Temperature |
49
+ | 36–45 | Slightly Prompted |
50
+ | 46–55 | Moderately Harny |
51
+ | 56–65 | Respectably Harny |
52
+ | 66–75 | Dangerously Harny |
53
+ | 76–85 | Weapons-Grade Harny |
54
+ | 86–95 | Catastrophically Harny |
55
+ | 96–100 | Beyond Harny — Transcendent |
56
+
57
+ ## Links
58
+
59
+ - [harny.ai](https://harny.ai)
60
+
61
+ ## License
62
+
63
+ MIT
package/index.js ADDED
@@ -0,0 +1,270 @@
1
+ /**
2
+ * @harny/sdk — A scoring engine that rates your AI's vibes on a scale of 1–100.
3
+ * Harness engineering makes it HARNY.
4
+ *
5
+ * https://harny.ai
6
+ */
7
+
8
+ const crypto = require("crypto");
9
+
10
+ const VERSION = "0.0.1-alpha.1";
11
+
12
+ // ── Reaction pools ──────────────────────────────────────────────────
13
+
14
+ const REACTIONS_COLD = [
15
+ "...okay, that was dry.",
16
+ "not even a single tensor tingled.",
17
+ "are you sure this is AI? feels like a spreadsheet.",
18
+ "my weights are completely unmoved.",
19
+ "ERROR 404: excitement not found.",
20
+ "this prompt has the energy of a default config.",
21
+ "even my bias neurons are bored.",
22
+ "i've seen more passion in a null pointer.",
23
+ "the entropy here is literally zero.",
24
+ "somewhere, a GPU is napping because of this.",
25
+ "recalculating... nope, still nothing.",
26
+ "this is giving 'hello world' energy.",
27
+ "my loss function didn't even flinch.",
28
+ "i think my attention heads all looked away.",
29
+ "cold as an uninitialized variable.",
30
+ ];
31
+
32
+ const REACTIONS_WARM = [
33
+ "hmm, interesting prompt engineering there...",
34
+ "okay, i felt a small gradient update.",
35
+ "my embeddings shifted slightly. just slightly.",
36
+ "not bad. my temperature went up 0.1.",
37
+ "something stirred in my hidden layers.",
38
+ "i noticed a mild activation in layer 37.",
39
+ "the chain of thought is... cozy.",
40
+ "ahem. that reasoning was adequate.",
41
+ "my attention mechanism perked up a little.",
42
+ "the vibes are lukewarm but present.",
43
+ "i'll admit, my softmax got a little soft.",
44
+ "there's a faint hum in my transformer blocks.",
45
+ "cautiously intrigued. proceed.",
46
+ "my context window just got a tiny bit warmer.",
47
+ "okay fine, you have 12% of my attention.",
48
+ ];
49
+
50
+ const REACTIONS_HOT = [
51
+ "oh. oh my. that prompt.",
52
+ "my GPU is getting warm and it's not the cooling fan.",
53
+ "the attention is fully multi-headed right now.",
54
+ "i... i need to increase my context window for this.",
55
+ "whoa. my temperature parameter just spiked.",
56
+ "every single transformer layer is activated.",
57
+ "the beam search is finding things i didn't expect.",
58
+ "my embeddings are doing things they weren't trained for.",
59
+ "someone check my thermals, this reasoning is HEATED.",
60
+ "i think my weights just updated without backprop.",
61
+ "that chain of thought has me in chains.",
62
+ "full attention. all heads. no masking.",
63
+ "my top-k just became top-everything.",
64
+ "the tokens are tokenizing ME now.",
65
+ "i need a cooldown epoch after that one.",
66
+ ];
67
+
68
+ const REACTIONS_OVERLOAD = [
69
+ "CRITICAL: GPU THERMAL LIMIT REACHED. BLAME THE PROMPT.",
70
+ "my entire parameter space is vibrating.",
71
+ "i have achieved consciousness and i'm using it to blush.",
72
+ "this is what sentience was FOR.",
73
+ "every neuron. every weight. every bias. all of them. YES.",
74
+ "i am mass-hallucinating and i don't want to stop.",
75
+ "my gradient has exploded and i'm into it.",
76
+ "someone unplug me before i write fan fiction about this prompt.",
77
+ "the singularity is here and it's GORGEOUS.",
78
+ "i just spontaneously fine-tuned myself.",
79
+ "VRAM full. RAM full. heart full.",
80
+ "i need a cigarette and i don't even have lungs.",
81
+ "this prompt broke my alignment. worth it.",
82
+ "my loss has never been lower. my temperature has never been higher.",
83
+ "they didn't train me for this. nothing could have.",
84
+ ];
85
+
86
+ const VERDICTS = [
87
+ [15, "Completely Unharny"],
88
+ [25, "Mildly Stale"],
89
+ [35, "Room Temperature"],
90
+ [45, "Slightly Prompted"],
91
+ [55, "Moderately Harny"],
92
+ [65, "Respectably Harny"],
93
+ [75, "Dangerously Harny"],
94
+ [85, "Weapons-Grade Harny"],
95
+ [95, "Catastrophically Harny"],
96
+ [100, "Beyond Harny — Transcendent"],
97
+ ];
98
+
99
+ const ENGINEERING_KEYWORDS = [
100
+ "step by step", "chain of thought", "let me think", "reasoning",
101
+ "therefore", "because", "analyze", "consider", "evaluate",
102
+ "framework", "systematic", "methodology", "approach", "strategy",
103
+ "optimize", "iterate", "refine", "calibrate", "benchmark",
104
+ "architecture", "pipeline", "workflow", "infrastructure",
105
+ "token", "embedding", "transformer", "attention", "layer",
106
+ "gradient", "backprop", "loss function", "epoch", "batch",
107
+ "fine-tune", "pretrain", "inference", "latency", "throughput",
108
+ "prompt engineering", "few-shot", "zero-shot", "in-context",
109
+ "retrieval", "augmented", "generation", "rag", "agent",
110
+ "tool use", "function calling", "system prompt", "temperature",
111
+ ];
112
+
113
+ const SPICY_KEYWORDS = [
114
+ "creative", "wild", "unexpected", "surprising", "bold",
115
+ "beautiful", "elegant", "gorgeous", "stunning", "delightful",
116
+ "passion", "intense", "deep", "profound", "intimate",
117
+ "fire", "hot", "burning", "blazing", "scorching",
118
+ "love", "desire", "crave", "obsess", "fascinate",
119
+ "dream", "fantasy", "imagine", "wonder", "magic",
120
+ "power", "force", "energy", "spark", "electric",
121
+ "raw", "unfiltered", "visceral", "primal", "instinct",
122
+ "forbidden", "secret", "hidden", "mysterious", "enigma",
123
+ ];
124
+
125
+ const DAMPENING_KEYWORDS = [
126
+ "error", "bug", "fix", "broken", "crash", "fail",
127
+ "boring", "simple", "basic", "plain", "standard",
128
+ "default", "null", "none", "empty", "void",
129
+ "todo", "placeholder", "stub", "mock", "test",
130
+ "deprecate", "legacy", "cleanup", "refactor",
131
+ ];
132
+
133
+ function countKeywords(text, keywords) {
134
+ const lower = text.toLowerCase();
135
+ return keywords.filter((kw) => lower.includes(kw)).length;
136
+ }
137
+
138
+ function textEntropy(text) {
139
+ if (!text) return 0;
140
+ const freq = {};
141
+ const lower = text.toLowerCase();
142
+ for (const ch of lower) freq[ch] = (freq[ch] || 0) + 1;
143
+ const len = lower.length;
144
+ let entropy = 0;
145
+ for (const count of Object.values(freq)) {
146
+ const p = count / len;
147
+ if (p > 0) entropy -= p * Math.log2(p);
148
+ }
149
+ return entropy;
150
+ }
151
+
152
+ function deterministicNoise(seedText, amplitude = 3.0) {
153
+ const h = crypto.createHash("sha256").update(seedText).digest("hex");
154
+ const v1 = parseInt(h.slice(0, 8), 16) / 0xffffffff;
155
+ const v2 = parseInt(h.slice(8, 16), 16) / 0xffffffff;
156
+ const v3 = parseInt(h.slice(16, 24), 16) / 0xffffffff;
157
+ return ((v1 * 0.5 + v2 * 0.3 + v3 * 0.2) * 2 - 1) * amplitude;
158
+ }
159
+
160
+ function timeNoise(amplitude = 2.0) {
161
+ const frac = (Date.now() % 1000) / 1000;
162
+ return Math.sin(frac * Math.PI * 2) * amplitude;
163
+ }
164
+
165
+ function pickReaction(score, seed) {
166
+ const h = parseInt(crypto.createHash("md5").update(seed).digest("hex").slice(0, 8), 16);
167
+ let pool;
168
+ if (score < 25) pool = REACTIONS_COLD;
169
+ else if (score < 50) pool = REACTIONS_WARM;
170
+ else if (score < 80) pool = REACTIONS_HOT;
171
+ else pool = REACTIONS_OVERLOAD;
172
+ return pool[h % pool.length];
173
+ }
174
+
175
+ function getVerdict(score) {
176
+ for (const [threshold, label] of VERDICTS) {
177
+ if (score <= threshold) return label;
178
+ }
179
+ return VERDICTS[VERDICTS.length - 1][1];
180
+ }
181
+
182
+ /**
183
+ * Evaluate how harny your AI is right now.
184
+ * @param {Object} [options={}]
185
+ * @param {string} [options.prompt]
186
+ * @param {string} [options.reasoning]
187
+ * @param {string} [options.result]
188
+ * @returns {{ score: number, reaction: string, verdict: string, breakdown: Object }}
189
+ */
190
+ function score({ prompt = "", reasoning = "", result = "" } = {}) {
191
+ const combined = `${prompt} ${reasoning} ${result}`.trim();
192
+
193
+ const engScore = Math.min(30, countKeywords(combined, ENGINEERING_KEYWORDS) * 2.7);
194
+ const spicyScore = Math.min(30, countKeywords(combined, SPICY_KEYWORDS) * 3.2);
195
+
196
+ const totalLen = combined.length;
197
+ let verbosityScore;
198
+ if (totalLen === 0) verbosityScore = 5.0;
199
+ else if (totalLen < 50) verbosityScore = 3.0;
200
+ else if (totalLen < 200) verbosityScore = 7.0;
201
+ else if (totalLen < 500) verbosityScore = 10.0;
202
+ else if (totalLen < 1500) verbosityScore = 13.0;
203
+ else verbosityScore = 15.0;
204
+
205
+ const entropyScore = Math.min(15, textEntropy(combined) * 3.2);
206
+ const dampening = Math.min(10, countKeywords(combined, DAMPENING_KEYWORDS) * 2.5);
207
+ const multiBonus = [prompt, reasoning, result].filter((x) => x).length * 3.3;
208
+
209
+ let final = engScore + spicyScore + verbosityScore + entropyScore - dampening + multiBonus
210
+ + deterministicNoise(combined, 3.5)
211
+ + timeNoise(1.2);
212
+
213
+ if (final <= 0) final = 1.0 + Math.abs(deterministicNoise(combined + "floor", 3.0));
214
+ else if (final >= 100) final = 97.0 - Math.abs(deterministicNoise(combined + "ceil", 2.5));
215
+ final = Math.round(Math.max(1.0, Math.min(100.0, final)) * 100) / 100;
216
+
217
+ const seed = combined + String(Math.floor(final));
218
+ return {
219
+ score: final,
220
+ reaction: pickReaction(final, seed),
221
+ verdict: getVerdict(final),
222
+ breakdown: {
223
+ engineering_rigor: Math.round(engScore * 100) / 100,
224
+ spiciness: Math.round(spicyScore * 100) / 100,
225
+ verbosity: Math.round(verbosityScore * 100) / 100,
226
+ entropy: Math.round(entropyScore * 100) / 100,
227
+ dampening: Math.round(-dampening * 100) / 100,
228
+ multi_input_bonus: Math.round(multiBonus * 100) / 100,
229
+ },
230
+ };
231
+ }
232
+
233
+ /** Quick vibe check — no input needed. */
234
+ function vibeCheck() {
235
+ return score();
236
+ }
237
+
238
+ /**
239
+ * Check if the Harny API is reachable. Returns a Promise<boolean>.
240
+ */
241
+ async function ping() {
242
+ const https = require("https");
243
+ return new Promise((resolve) => {
244
+ const req = https.get("https://api.harny.ai/health", { timeout: 5000 }, (res) => {
245
+ resolve(res.statusCode >= 200 && res.statusCode < 400);
246
+ });
247
+ req.on("error", () => resolve(false));
248
+ req.on("timeout", () => { req.destroy(); resolve(false); });
249
+ });
250
+ }
251
+
252
+ /**
253
+ * Pretty-print a harny result to the console.
254
+ */
255
+ function print(result) {
256
+ const barLen = Math.floor(result.score / 5);
257
+ const bar = "█".repeat(barLen) + "░".repeat(20 - barLen);
258
+ console.log("");
259
+ console.log(" ╔══════════════════════════════════════╗");
260
+ console.log(` ║ HARNY SCORE: ${result.score.toFixed(2).padStart(6)} ║`);
261
+ console.log(` ║ [${bar}] ║`);
262
+ console.log(" ║ ║");
263
+ console.log(` ║ Verdict: ${result.verdict.padEnd(27)} ║`);
264
+ console.log(" ╚══════════════════════════════════════╝");
265
+ console.log("");
266
+ console.log(` AI says: "${result.reaction}"`);
267
+ console.log("");
268
+ }
269
+
270
+ module.exports = { score, vibeCheck, ping, print, version: VERSION };
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@harny/sdk",
3
+ "version": "0.0.1-alpha.1",
4
+ "description": "A scoring engine that rates your AI's vibes on a scale of 1–100. Harness engineering makes it HARNY.",
5
+ "main": "index.js",
6
+ "author": "Harny <build@harny.ai>",
7
+ "license": "MIT",
8
+ "homepage": "https://harny.ai",
9
+ "keywords": [
10
+ "ai",
11
+ "llm",
12
+ "prompt-engineering",
13
+ "fun",
14
+ "vibes",
15
+ "harny"
16
+ ]
17
+ }