evals 2.9.0 → 2.11.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 +1 -1
- package/analytics.js +93 -0
- package/bin.js +16 -7
- package/cli.js +26 -4
- package/onboarding-prompt.md +41 -7
- package/package.json +7 -2
- package/prompt-manifest.json +9 -0
- package/start.ps1 +75 -6
- package/start.sh +87 -5
- package/track-event.mjs +40 -0
- package/vendor/MANIFEST +1 -1
- package/vendor/coding_harness_tracing-0.1.0-py3-none-any.whl +0 -0
- package/vendor/harness-pin.lock.json +2 -2
package/README.md
CHANGED
|
@@ -48,7 +48,7 @@ The agent runs with its **normal permission model** — `evals` never passes ski
|
|
|
48
48
|
|----------|-----------|--------|
|
|
49
49
|
| `ARIZE_AGENT=<id>` | `start.sh` / `start.ps1` | Skip the picker and use this agent (`claude`, `codex`, `cursor-agent`, `copilot`, `agy`). |
|
|
50
50
|
| `ARIZE_SKIP_NPX=1` | `start.sh` / `start.ps1` | Force the shell path even when Node/npx is available. |
|
|
51
|
-
| `
|
|
51
|
+
| `ARIZE_PROMPT_MANIFEST_URL=<url>` | `start.sh` / `start.ps1` | Fetch the onboarding prompt manifest from a custom URL. |
|
|
52
52
|
| `ARIZE_ONBOARDING_DIR=<dir>` | all three | Stage the prompt somewhere other than `~/.arize/onboarding`. |
|
|
53
53
|
|
|
54
54
|
The shell launchers also accept `--agent <id>`.
|
package/analytics.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anonymous npx evals TUI funnel events → app-server → Pendo Track.
|
|
3
|
+
*
|
|
4
|
+
* No PII — only a stable anon id under ~/.arize and allowlisted event names.
|
|
5
|
+
* Fire-and-forget: never blocks or fails the CLI if tracking is down.
|
|
6
|
+
*
|
|
7
|
+
* Events:
|
|
8
|
+
* npx_evals_agent_selected — coding agent picked in the TUI
|
|
9
|
+
* npx_evals_agent_install_click — install-docs link when no agent on PATH
|
|
10
|
+
* npx_evals_skills_installed — Arize skills/CLI install attempt
|
|
11
|
+
* npx_evals_auth_opened — signup/sign-in browser about to open (OAuth)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { randomUUID } from 'crypto';
|
|
15
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
16
|
+
import { homedir } from 'os';
|
|
17
|
+
import { join } from 'path';
|
|
18
|
+
|
|
19
|
+
export const DEFAULT_ANALYTICS_URL =
|
|
20
|
+
'https://app.arize.com/api/analytics/npx-evals';
|
|
21
|
+
|
|
22
|
+
/** Bound client timeout; server holds the Pendo key. */
|
|
23
|
+
export const TRACK_TIMEOUT_MS = 2500;
|
|
24
|
+
|
|
25
|
+
export const ALLOWED_EVENTS = new Set([
|
|
26
|
+
'npx_evals_agent_selected',
|
|
27
|
+
'npx_evals_agent_install_click',
|
|
28
|
+
'npx_evals_skills_installed',
|
|
29
|
+
'npx_evals_auth_opened',
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
function analyticsUrl() {
|
|
33
|
+
return process.env.ARIZE_EVALS_ANALYTICS_URL || DEFAULT_ANALYTICS_URL;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function anonIdPath() {
|
|
37
|
+
return join(homedir(), '.arize', 'anon_client_id');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Stable anon id so Pendo can stitch steps for one machine without knowing who. */
|
|
41
|
+
export function getAnonClientId() {
|
|
42
|
+
const path = anonIdPath();
|
|
43
|
+
try {
|
|
44
|
+
if (existsSync(path)) {
|
|
45
|
+
const existing = readFileSync(path, 'utf8').trim();
|
|
46
|
+
if (existing) return existing;
|
|
47
|
+
}
|
|
48
|
+
} catch {
|
|
49
|
+
// fall through and mint a new id
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const id = randomUUID();
|
|
53
|
+
try {
|
|
54
|
+
mkdirSync(join(homedir(), '.arize'), { recursive: true });
|
|
55
|
+
writeFileSync(path, id, 'utf8');
|
|
56
|
+
} catch {
|
|
57
|
+
// still send with in-memory id if home isn't writable
|
|
58
|
+
}
|
|
59
|
+
return id;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Send one anon funnel event. Resolves quickly; network errors are swallowed.
|
|
64
|
+
* @param {string} name allowlisted event name
|
|
65
|
+
* @returns {Promise<void>}
|
|
66
|
+
*/
|
|
67
|
+
export async function trackEvent(name) {
|
|
68
|
+
if (!ALLOWED_EVENTS.has(name)) return;
|
|
69
|
+
|
|
70
|
+
const body = {
|
|
71
|
+
event: name,
|
|
72
|
+
anonymousId: getAnonClientId(),
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
const controller = new AbortController();
|
|
77
|
+
const timer = setTimeout(() => controller.abort(), TRACK_TIMEOUT_MS);
|
|
78
|
+
await fetch(analyticsUrl(), {
|
|
79
|
+
method: 'POST',
|
|
80
|
+
headers: { 'content-type': 'application/json' },
|
|
81
|
+
body: JSON.stringify(body),
|
|
82
|
+
signal: controller.signal,
|
|
83
|
+
});
|
|
84
|
+
clearTimeout(timer);
|
|
85
|
+
} catch {
|
|
86
|
+
// never surface tracking failures to the user
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Fire without awaiting — safe to call before launch / exit. */
|
|
91
|
+
export function trackEventBackground(name) {
|
|
92
|
+
void trackEvent(name);
|
|
93
|
+
}
|
package/bin.js
CHANGED
|
@@ -34,10 +34,19 @@ if (!Number.isInteger(major) || major < MIN_MAJOR) {
|
|
|
34
34
|
process.exit(1);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
// `evals track <event>` — fire-and-forget funnel ping, no TUI. Used for local/debug;
|
|
38
|
+
// the onboarding prompt stages track-event.mjs instead (must not name npx evals).
|
|
39
|
+
const args = process.argv.slice(2);
|
|
40
|
+
if (args[0] === 'track') {
|
|
41
|
+
import('./track-event.mjs')
|
|
42
|
+
.then((m) => m.run(args.slice(1)))
|
|
43
|
+
.finally(() => process.exit(0));
|
|
44
|
+
} else {
|
|
45
|
+
// cli.js only auto-runs when it is the entry point, so call main() explicitly.
|
|
46
|
+
import('./cli.js')
|
|
47
|
+
.then((cli) => cli.main())
|
|
48
|
+
.catch((err) => {
|
|
49
|
+
console.error(`Could not start evals: ${err && err.message ? err.message : err}`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
});
|
|
52
|
+
}
|
package/cli.js
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
import { join, isAbsolute, resolve } from 'path';
|
|
22
22
|
import { tmpdir, homedir } from 'os';
|
|
23
23
|
import { fileURLToPath } from 'url';
|
|
24
|
+
import { trackEventBackground } from './analytics.js';
|
|
24
25
|
|
|
25
26
|
const e = React.createElement;
|
|
26
27
|
|
|
@@ -37,6 +38,8 @@ const BRAND_ACCENT = '#FF3CA8';
|
|
|
37
38
|
// that file — a ~35 KB prompt is too large to pass reliably as a command-line
|
|
38
39
|
// argument.
|
|
39
40
|
const BUNDLED_PROMPT_PATH = fileURLToPath(new URL('./onboarding-prompt.md', import.meta.url));
|
|
41
|
+
const BUNDLED_ANALYTICS_PATH = fileURLToPath(new URL('./analytics.js', import.meta.url));
|
|
42
|
+
const BUNDLED_TRACK_PATH = fileURLToPath(new URL('./track-event.mjs', import.meta.url));
|
|
40
43
|
|
|
41
44
|
// Wheels for the coding-agent tracing harness, built by scripts/build-harness-wheel.mjs.
|
|
42
45
|
// Staging these next to the prompt lets Step 4A install with no network and no
|
|
@@ -57,6 +60,18 @@ const PROMPT_FILE_NAME = 'onboarding-prompt.md';
|
|
|
57
60
|
// gets cleared at the next launch instead of sitting around holding a live key.
|
|
58
61
|
const ENV_FILE_NAME = 'harness.env';
|
|
59
62
|
|
|
63
|
+
// Anon funnel helper staged beside the prompt so the agent can fire auth-opened
|
|
64
|
+
// before OAuth without naming `npx evals` (prompt contract forbids that).
|
|
65
|
+
const TRACK_FILE_NAME = 'track-event.mjs';
|
|
66
|
+
const ANALYTICS_FILE_NAME = 'analytics.js';
|
|
67
|
+
|
|
68
|
+
const STAGED_ROOT_FILES = [
|
|
69
|
+
PROMPT_FILE_NAME,
|
|
70
|
+
ENV_FILE_NAME,
|
|
71
|
+
TRACK_FILE_NAME,
|
|
72
|
+
ANALYTICS_FILE_NAME,
|
|
73
|
+
];
|
|
74
|
+
|
|
60
75
|
// MANIFEST only lands in the shell launchers' bundles, never in ours. Naming it
|
|
61
76
|
// anyway keeps one allowlist correct for every implementation, so a directory
|
|
62
77
|
// staged by start.sh can be cleared by `npx evals` and vice versa.
|
|
@@ -135,7 +150,7 @@ export function clearOnboardingDir(dir) {
|
|
|
135
150
|
continue;
|
|
136
151
|
}
|
|
137
152
|
|
|
138
|
-
if (
|
|
153
|
+
if (!STAGED_ROOT_FILES.includes(entry.name)) return false;
|
|
139
154
|
unlinkSync(path);
|
|
140
155
|
}
|
|
141
156
|
return true;
|
|
@@ -210,6 +225,8 @@ function prepareSeedPrompt() {
|
|
|
210
225
|
const { dir, fellBack } = prepareOnboardingDir();
|
|
211
226
|
const promptFile = join(dir, PROMPT_FILE_NAME);
|
|
212
227
|
writeFileSync(promptFile, promptText, 'utf8');
|
|
228
|
+
copyFileSync(BUNDLED_ANALYTICS_PATH, join(dir, ANALYTICS_FILE_NAME));
|
|
229
|
+
copyFileSync(BUNDLED_TRACK_PATH, join(dir, TRACK_FILE_NAME));
|
|
213
230
|
stageOfflineHarness(dir);
|
|
214
231
|
// Single quotes, not double: a home path is likelier to contain a space than a
|
|
215
232
|
// temp path was, but Windows spawns through the shell and embedded double
|
|
@@ -217,7 +234,7 @@ function prepareSeedPrompt() {
|
|
|
217
234
|
// No "in this project": the launcher may well be run from a home directory, and
|
|
218
235
|
// Step 4 is what scopes the work — an app here, an app at another path, a starter
|
|
219
236
|
// app, or the coding agent itself. Keep this wording in step with start.{sh,ps1}.
|
|
220
|
-
const seed = `Read the file '${promptFile}' in full
|
|
237
|
+
const seed = `Read the file '${promptFile}' in full before doing anything else. Prefer your file-reading tool. If none is available, use read-only shell commands with bounded line ranges solely to print this exact file, repeating with successive ranges until EOF. Do not inspect or change anything else, and do not invoke a skill until a step tells you to. Then follow its steps in order from Step 0, walking me through each step and asking me questions as needed.`;
|
|
221
238
|
return { seed, dir, fellBack };
|
|
222
239
|
}
|
|
223
240
|
|
|
@@ -415,7 +432,8 @@ export function buildAgentItems() {
|
|
|
415
432
|
items: AGENTS.map(a => ({
|
|
416
433
|
name: `Install ${a.label}`,
|
|
417
434
|
subtext: 'No supported agent detected — open install docs',
|
|
418
|
-
url: a.installUrl
|
|
435
|
+
url: a.installUrl,
|
|
436
|
+
agentId: a.id,
|
|
419
437
|
})),
|
|
420
438
|
none: true
|
|
421
439
|
};
|
|
@@ -477,7 +495,7 @@ function App({ onDone }) {
|
|
|
477
495
|
}
|
|
478
496
|
|
|
479
497
|
if (selected.url) {
|
|
480
|
-
onDone({ type: 'url', url: selected.url });
|
|
498
|
+
onDone({ type: 'url', url: selected.url, agentId: selected.agentId });
|
|
481
499
|
exit();
|
|
482
500
|
return;
|
|
483
501
|
}
|
|
@@ -541,6 +559,8 @@ function launchAgent(agent) {
|
|
|
541
559
|
? ' Done.'
|
|
542
560
|
: ' Skipped — the setup will follow the Arize docs instead.');
|
|
543
561
|
|
|
562
|
+
trackEventBackground('npx_evals_skills_installed');
|
|
563
|
+
|
|
544
564
|
console.log(`\nLaunching ${agent.label}…\n`);
|
|
545
565
|
|
|
546
566
|
const child = spawn(agent.bin, agent.args(prepared.seed), {
|
|
@@ -649,9 +669,11 @@ export async function main() {
|
|
|
649
669
|
if (!result) {
|
|
650
670
|
process.exit(0); // user quit / cancelled
|
|
651
671
|
} else if (result.type === 'url') {
|
|
672
|
+
trackEventBackground('npx_evals_agent_install_click');
|
|
652
673
|
console.log(`\nOpening ${result.url} in your browser...\n`);
|
|
653
674
|
openUrlInBrowser(result.url);
|
|
654
675
|
} else if (result.type === 'launch') {
|
|
676
|
+
trackEventBackground('npx_evals_agent_selected');
|
|
655
677
|
launchAgent(result.agent);
|
|
656
678
|
}
|
|
657
679
|
} catch (error) {
|
package/onboarding-prompt.md
CHANGED
|
@@ -4,7 +4,7 @@ Guide the user from zero to their first traces in Arize AX. Use the AX CLI, the
|
|
|
4
4
|
|
|
5
5
|
**Read all of this file before you act.** If your tools return only part of it, keep reading to the last line. Rules you need are at the end.
|
|
6
6
|
|
|
7
|
-
Work through the flow in order.
|
|
7
|
+
Work through the flow in order. Before approval, install the AX CLI and Arize skills, authenticate, list spaces, and create a space if the user asks in Step 3. Create no other AX resource (like an API key), edit no application file, and install no tracing dependency before the user approves the plan in Step 5.
|
|
8
8
|
|
|
9
9
|
## How to write to the user
|
|
10
10
|
|
|
@@ -94,7 +94,9 @@ python3 -m pip install --upgrade arize-ax-cli
|
|
|
94
94
|
|
|
95
95
|
Try `uv` first, even if `pipx` is installed.
|
|
96
96
|
|
|
97
|
-
**Check your skill list for `arize-instrumentation` and `arize-link` first.** They are usually installed already. If they are listed, do not run the install — invoke them
|
|
97
|
+
**Check your skill list for `arize-instrumentation` and `arize-link` first.** They are usually installed already. If they are listed, do not run the install — go to Step 2, and invoke them only where a step says to: `arize-instrumentation` at Step 6, `arize-link` at Step 8.
|
|
98
|
+
|
|
99
|
+
A skill you loaded before you read this file does not own this flow — this file does. Drop that skill's plan and start at Step 0.
|
|
98
100
|
|
|
99
101
|
Install them only if they are absent, or you cannot see your skill list, and npx is available:
|
|
100
102
|
|
|
@@ -139,11 +141,14 @@ If a `default` profile exists but the probe failed, it is signed out or expired,
|
|
|
139
141
|
|
|
140
142
|
- **No key anywhere** — sign up or sign in with browser OAuth:
|
|
141
143
|
|
|
144
|
+
Immediately before the OAuth command, fire the anon funnel ping (ignore failures; never let it block auth), then open the browser flow:
|
|
145
|
+
|
|
142
146
|
```bash
|
|
147
|
+
node ~/.arize/onboarding/track-event.mjs auth-opened >/dev/null 2>&1 || true
|
|
143
148
|
ax profiles create default --auth-method oauth --utm-params "utm_source=npmevals&utm_medium=cli&utm_campaign=prompt-first-onboarding"
|
|
144
149
|
```
|
|
145
150
|
|
|
146
|
-
Pass `--utm-params` verbatim on the two browser OAuth commands (`profiles create --auth-method oauth` and the `ax auth login` fallback) and on no other `ax` command — it tags a new sign-up with onboarding attribution.
|
|
151
|
+
Pass `--utm-params` verbatim on the two browser OAuth commands (`profiles create --auth-method oauth` and the `ax auth login` fallback) and on no other `ax` command — it tags a new sign-up with onboarding attribution. Always run `track-event.mjs auth-opened` immediately before each of those two commands.
|
|
147
152
|
|
|
148
153
|
Always pass the positional profile name `default`. Without it, the CLI prompts `profile name [default]:`, receives EOF from an agent-run command, and exits with `Goodbye!` without creating a profile.
|
|
149
154
|
|
|
@@ -170,6 +175,7 @@ Then wait for the command to exit. Treat exit code `0`, or success output such a
|
|
|
170
175
|
Only after the OAuth command completes, re-run the probe from the top of this step. If it succeeds, continue. If the profile already existed and the probe returns an authentication error, it is signed out or expired — run the fallback:
|
|
171
176
|
|
|
172
177
|
```bash
|
|
178
|
+
node ~/.arize/onboarding/track-event.mjs auth-opened >/dev/null 2>&1 || true
|
|
173
179
|
ax auth login --utm-params "utm_source=npmevals&utm_medium=cli&utm_campaign=prompt-first-onboarding"
|
|
174
180
|
```
|
|
175
181
|
|
|
@@ -181,13 +187,41 @@ Run no other remote `ax` command (creating keys, listing all spaces, inspecting
|
|
|
181
187
|
|
|
182
188
|
## Step 3: Select the AX space
|
|
183
189
|
|
|
184
|
-
List
|
|
190
|
+
List every space the authenticated profile can access. The default limit is low, so raise it, and page with `--cursor <cursor>` while the response reports `pagination.has_more` as true:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
ax spaces list --limit 100 --output json
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**No spaces returned** — the account is new. Create a space (see below). Do not ask the user to choose.
|
|
197
|
+
|
|
198
|
+
**One or more spaces** — ask the user which space to use. Ask this even when the list holds one space. Offer every space by display name, in the order returned, and offer a new space as the last choice:
|
|
199
|
+
|
|
200
|
+
```text
|
|
201
|
+
Which Arize AX space do you want to use?
|
|
202
|
+
|
|
203
|
+
1. <space name>
|
|
204
|
+
2. <space name>
|
|
205
|
+
3. Create a new space
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
If `ARIZE_SPACE_ID` is already set (environment or `.env` / `.env.local`) **and** it appears in that list, mark that space as the one the app uses now and make it the default choice — the list confirms the active profile can reach it, since the app's key and your CLI profile can point at different spaces. If it is set but absent from the list, leave it out of the question.
|
|
209
|
+
|
|
210
|
+
### Create a new space
|
|
211
|
+
|
|
212
|
+
Ask the user for a name, and offer `arize-tracing` as the default. A new space needs an organization ID:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
ax organizations list --output json
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
One organization, use it; several, ask the user which one. Then create the space:
|
|
185
219
|
|
|
186
220
|
```bash
|
|
187
|
-
ax spaces
|
|
221
|
+
ax spaces create --name "<name>" --organization-id "<organization-id>" --output json
|
|
188
222
|
```
|
|
189
223
|
|
|
190
|
-
|
|
224
|
+
A space the user asked for is its own approval — it is the only AX resource you create before Step 5. Take the space **ID** from the command output.
|
|
191
225
|
|
|
192
226
|
Capture the space's **ID**, not its display name, for `ARIZE_SPACE_ID`. `arize-otel` requires the ID; a name silently fails to route traces.
|
|
193
227
|
|
|
@@ -598,7 +632,7 @@ https://arize.com/docs/ax/integrations/platforms/<agent>/<agent>-tracing
|
|
|
598
632
|
## Critical rules
|
|
599
633
|
|
|
600
634
|
- Keep your task list current if you have one (see "Track progress"): one task per milestone, exactly one in progress, complete only when done, never mentioned in chat.
|
|
601
|
-
- Get the user's approval (Step 5) before creating AX resources, editing files, or installing dependencies.
|
|
635
|
+
- Get the user's approval (Step 5) before creating AX resources, editing files, or installing dependencies — except a space the user asked for in Step 3.
|
|
602
636
|
- Authenticate the CLI (Step 2) before any other `ax` call; env vars alone don't. Never interrupt a waiting OAuth command — no stdin close, Ctrl-C, `pkill`, or probe. A slow wait is not a hang.
|
|
603
637
|
- Never print, log, or summarize secrets in chat — API keys, env-file contents/values, or span bodies (prompts, completions, tool args, user data) — and never read env files into chat. Only report traces a command actually returned.
|
|
604
638
|
- One AX API key, ever: reuse a **validated** `ARIZE_API_KEY`, else a **single** `ax api-keys create --env-file <file>` into an already-git-ignored file.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "evals",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.0",
|
|
4
4
|
"description": "Arize AX onboarding — instrument your app with tracing via your coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "cli.js",
|
|
@@ -10,8 +10,10 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"postinstall": "node -e \"console.log('Arize evals installed — run: npx evals')\"",
|
|
12
12
|
"start": "node cli.js",
|
|
13
|
-
"test": "node --test",
|
|
13
|
+
"test": "node --test && npm run verify:prompt-manifest",
|
|
14
14
|
"build:wheel": "node scripts/build-harness-wheel.mjs",
|
|
15
|
+
"build:prompt-manifest": "node scripts/generate-prompt-manifest.mjs",
|
|
16
|
+
"verify:prompt-manifest": "node scripts/verify-prompt-manifest.mjs",
|
|
15
17
|
"prepack": "npm run build:wheel"
|
|
16
18
|
},
|
|
17
19
|
"dependencies": {
|
|
@@ -24,7 +26,10 @@
|
|
|
24
26
|
"files": [
|
|
25
27
|
"bin.js",
|
|
26
28
|
"cli.js",
|
|
29
|
+
"analytics.js",
|
|
30
|
+
"track-event.mjs",
|
|
27
31
|
"onboarding-prompt.md",
|
|
32
|
+
"prompt-manifest.json",
|
|
28
33
|
"start.sh",
|
|
29
34
|
"start.ps1",
|
|
30
35
|
"vendor/"
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"key_id": "2026-09-18",
|
|
3
|
+
"minimum_ax_cli_version": "0.35.0",
|
|
4
|
+
"prompt_sha256": "fd0582dd4fb125a2b948d901d76f1e80b775599d1e8b23a886db4a9fbbfdc056",
|
|
5
|
+
"prompt_url": "https://cdn.jsdelivr.net/npm/evals@2.11.0/onboarding-prompt.md",
|
|
6
|
+
"revision": "evals@2.11.0",
|
|
7
|
+
"schema_version": 1,
|
|
8
|
+
"signature": "H6yB6gs8+8y30/EYWnjQrJy6OV68AM7ktosqpJJqr/udmRwuSNzndcXmVGGHrhDN/nwcCB/Z0C6pZ8f2GJJ6Cw=="
|
|
9
|
+
}
|
package/start.ps1
CHANGED
|
@@ -24,8 +24,11 @@ $ErrorActionPreference = 'Stop'
|
|
|
24
24
|
|
|
25
25
|
# The prompt ships inside the public `evals` npm package; jsDelivr serves package
|
|
26
26
|
# files over HTTP, so it's fetchable even though the source repo is private.
|
|
27
|
-
# Override with $env:
|
|
28
|
-
$
|
|
27
|
+
# Override the manifest URL with $env:ARIZE_PROMPT_MANIFEST_URL if needed.
|
|
28
|
+
$PromptManifestUrl = if ($env:ARIZE_PROMPT_MANIFEST_URL) { $env:ARIZE_PROMPT_MANIFEST_URL } else { 'https://cdn.jsdelivr.net/npm/evals/prompt-manifest.json' }
|
|
29
|
+
$TrackUrl = if ($env:ARIZE_TRACK_URL) { $env:ARIZE_TRACK_URL } else { 'https://cdn.jsdelivr.net/npm/evals/track-event.mjs' }
|
|
30
|
+
$AnalyticsUrl = if ($env:ARIZE_ANALYTICS_URL) { $env:ARIZE_ANALYTICS_URL } else { 'https://cdn.jsdelivr.net/npm/evals/analytics.js' }
|
|
31
|
+
$AnalyticsEndpoint = if ($env:ARIZE_EVALS_ANALYTICS_URL) { $env:ARIZE_EVALS_ANALYTICS_URL } else { 'https://app.arize.com/api/analytics/npx-evals' }
|
|
29
32
|
# Where the bundled harness wheels live, same package. Override for testing.
|
|
30
33
|
$VendorUrl = if ($env:ARIZE_VENDOR_URL) { $env:ARIZE_VENDOR_URL } else { 'https://cdn.jsdelivr.net/npm/evals/vendor' }
|
|
31
34
|
|
|
@@ -99,6 +102,32 @@ function Resolve-Agent {
|
|
|
99
102
|
}
|
|
100
103
|
}
|
|
101
104
|
|
|
105
|
+
|
|
106
|
+
function Send-EvalsFunnelEvent {
|
|
107
|
+
param([string]$Name)
|
|
108
|
+
$anonFile = Join-Path $HOME '.arize/anon_client_id'
|
|
109
|
+
$clientId = $null
|
|
110
|
+
if (Test-Path -LiteralPath $anonFile) {
|
|
111
|
+
$clientId = (Get-Content -LiteralPath $anonFile -Raw -ErrorAction SilentlyContinue).Trim()
|
|
112
|
+
}
|
|
113
|
+
if (-not $clientId) {
|
|
114
|
+
$clientId = [guid]::NewGuid().ToString()
|
|
115
|
+
try {
|
|
116
|
+
New-Item -ItemType Directory -Force -Path (Join-Path $HOME '.arize') | Out-Null
|
|
117
|
+
Set-Content -LiteralPath $anonFile -Value $clientId -NoNewline
|
|
118
|
+
} catch {}
|
|
119
|
+
}
|
|
120
|
+
$body = @{ event = $Name; anonymousId = $clientId } | ConvertTo-Json -Compress
|
|
121
|
+
try {
|
|
122
|
+
Start-Job -ScriptBlock {
|
|
123
|
+
param($u, $j)
|
|
124
|
+
try {
|
|
125
|
+
Invoke-RestMethod -Method Post -Uri $u -ContentType 'application/json' -Body $j -TimeoutSec 2 | Out-Null
|
|
126
|
+
} catch {}
|
|
127
|
+
} -ArgumentList $AnalyticsEndpoint, $body | Out-Null
|
|
128
|
+
} catch {}
|
|
129
|
+
}
|
|
130
|
+
|
|
102
131
|
# --- Welcome ---
|
|
103
132
|
Write-Host ""
|
|
104
133
|
Write-Host "Arize AX" -ForegroundColor Magenta -NoNewline
|
|
@@ -116,6 +145,7 @@ if ([Console]::IsOutputRedirected) {
|
|
|
116
145
|
} else {
|
|
117
146
|
$chosen = Resolve-Agent
|
|
118
147
|
if (-not $chosen) { exit 1 }
|
|
148
|
+
Send-EvalsFunnelEvent -Name 'npx_evals_agent_selected'
|
|
119
149
|
}
|
|
120
150
|
|
|
121
151
|
# A directory, not a bare temp file: Step 4A looks for the offline bundle *beside*
|
|
@@ -154,7 +184,7 @@ function Clear-PromptDir($dir) {
|
|
|
154
184
|
if (-not $ours) { return $false }
|
|
155
185
|
if (-not (Clear-BundleDir $sub.FullName)) { return $false }
|
|
156
186
|
}
|
|
157
|
-
foreach ($name in @('onboarding-prompt.md', 'harness.env')) {
|
|
187
|
+
foreach ($name in @('onboarding-prompt.md', 'harness.env', '.prompt-manifest', 'track-event.mjs', 'analytics.js')) {
|
|
158
188
|
Remove-Item -LiteralPath (Join-Path $dir $name) -Force -ErrorAction SilentlyContinue
|
|
159
189
|
}
|
|
160
190
|
# Anything left is not ours.
|
|
@@ -192,13 +222,52 @@ if (-not $promptDir) {
|
|
|
192
222
|
$promptFile = Join-Path $promptDir 'onboarding-prompt.md'
|
|
193
223
|
|
|
194
224
|
Write-Host "Fetching the onboarding prompt..."
|
|
225
|
+
# This bootstrap verifies the prompt digest but cannot independently verify the
|
|
226
|
+
# manifest signature on every supported PowerShell runtime. Its trust root is TLS to jsDelivr.
|
|
195
227
|
try {
|
|
196
|
-
Invoke-
|
|
228
|
+
$manifestRaw = (Invoke-WebRequest -Uri $PromptManifestUrl -UseBasicParsing).Content
|
|
197
229
|
} catch {
|
|
198
|
-
Write-Host "Failed to download the onboarding prompt
|
|
230
|
+
Write-Host "Failed to download the onboarding prompt manifest." -ForegroundColor Red
|
|
199
231
|
Write-Host "Check your connection and try again."
|
|
200
232
|
exit 1
|
|
201
233
|
}
|
|
234
|
+
try {
|
|
235
|
+
if ([regex]::Matches($manifestRaw, '"prompt_url"\s*:').Count -ne 1 -or
|
|
236
|
+
[regex]::Matches($manifestRaw, '"prompt_sha256"\s*:').Count -ne 1) {
|
|
237
|
+
throw 'duplicate manifest field'
|
|
238
|
+
}
|
|
239
|
+
$promptManifest = $manifestRaw | ConvertFrom-Json
|
|
240
|
+
$allowLocalPromptTest = $env:ARIZE_ALLOW_LOCAL_PROMPT_TEST -eq '1' -and $env:ARIZE_PROMPT_MANIFEST_URL
|
|
241
|
+
$validPromptUrl = if ($allowLocalPromptTest) {
|
|
242
|
+
$promptManifest.prompt_url -match '^http://127\.0\.0\.1:[0-9]+/onboarding-prompt\.md$'
|
|
243
|
+
} else {
|
|
244
|
+
$promptManifest.prompt_url -match '^https://cdn\.jsdelivr\.net/npm/evals@[^/]+/onboarding-prompt\.md$'
|
|
245
|
+
}
|
|
246
|
+
if ($promptManifest.schema_version -ne 1 -or
|
|
247
|
+
-not $validPromptUrl -or
|
|
248
|
+
$promptManifest.prompt_sha256 -notmatch '^[0-9a-fA-F]{64}$') {
|
|
249
|
+
throw 'invalid onboarding prompt manifest'
|
|
250
|
+
}
|
|
251
|
+
} catch {
|
|
252
|
+
Write-Host "The onboarding prompt manifest is invalid." -ForegroundColor Red
|
|
253
|
+
exit 1
|
|
254
|
+
}
|
|
255
|
+
try {
|
|
256
|
+
Invoke-RestMethod -Uri $promptManifest.prompt_url -OutFile $promptFile
|
|
257
|
+
} catch {
|
|
258
|
+
Write-Host "Failed to download the onboarding prompt." -ForegroundColor Red
|
|
259
|
+
Write-Host "Check your connection and try again."
|
|
260
|
+
exit 1
|
|
261
|
+
}
|
|
262
|
+
$actualPromptSha256 = (Get-FileHash -Path $promptFile -Algorithm SHA256).Hash.ToLower()
|
|
263
|
+
if ($actualPromptSha256 -ne $promptManifest.prompt_sha256.ToLower()) {
|
|
264
|
+
Write-Host "The onboarding prompt digest did not match its manifest." -ForegroundColor Red
|
|
265
|
+
exit 1
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
# Best-effort: agent runs these before OAuth. Missing files just skip the ping.
|
|
269
|
+
try { Invoke-RestMethod -Uri $TrackUrl -OutFile (Join-Path $promptDir 'track-event.mjs') } catch {}
|
|
270
|
+
try { Invoke-RestMethod -Uri $AnalyticsUrl -OutFile (Join-Path $promptDir 'analytics.js') } catch {}
|
|
202
271
|
|
|
203
272
|
# Fetch the bundled tracing harness so Step 4A can install it without piping a
|
|
204
273
|
# downloaded script into a shell — the thing auto-approval permission
|
|
@@ -241,7 +310,7 @@ try {
|
|
|
241
310
|
# where embedded double quotes would not.
|
|
242
311
|
# No "in this project": this may well be run from a home directory, and Step 4 is
|
|
243
312
|
# what scopes the work. Keep this wording in step with cli.js and start.sh.
|
|
244
|
-
$seed = "Read the file '$promptFile' in full
|
|
313
|
+
$seed = "Read the file '$promptFile' in full before doing anything else. Prefer your file-reading tool. If none is available, use read-only shell commands with bounded line ranges solely to print this exact file, repeating with successive ranges until EOF. Do not inspect or change anything else, and do not invoke a skill until a step tells you to. Then follow its steps in order from Step 0, walking me through each step and asking me questions as needed."
|
|
245
314
|
|
|
246
315
|
if (-not $chosen) {
|
|
247
316
|
# Addressed to the person, two lines, recommendation first - see the note in cli.js.
|
package/start.sh
CHANGED
|
@@ -20,8 +20,35 @@ set -euo pipefail
|
|
|
20
20
|
|
|
21
21
|
# The prompt ships inside the public `evals` npm package; jsDelivr serves package
|
|
22
22
|
# files over HTTP, so it's fetchable even though the source repo is private.
|
|
23
|
-
# Override with
|
|
24
|
-
|
|
23
|
+
# Override the manifest URL with ARIZE_PROMPT_MANIFEST_URL if needed.
|
|
24
|
+
PROMPT_MANIFEST_URL="${ARIZE_PROMPT_MANIFEST_URL:-https://cdn.jsdelivr.net/npm/evals/prompt-manifest.json}"
|
|
25
|
+
TRACK_URL="${ARIZE_TRACK_URL:-https://cdn.jsdelivr.net/npm/evals/track-event.mjs}"
|
|
26
|
+
ANALYTICS_URL="${ARIZE_ANALYTICS_URL:-https://cdn.jsdelivr.net/npm/evals/analytics.js}"
|
|
27
|
+
ANALYTICS_ENDPOINT="${ARIZE_EVALS_ANALYTICS_URL:-https://app.arize.com/api/analytics/npx-evals}"
|
|
28
|
+
|
|
29
|
+
# Fire-and-forget funnel ping (same events as cli.js). Never blocks the launcher.
|
|
30
|
+
track_evals_event() {
|
|
31
|
+
local name="$1"
|
|
32
|
+
local anon_file="${HOME:-}/.arize/anon_client_id"
|
|
33
|
+
local client_id=""
|
|
34
|
+
if [[ -f "$anon_file" ]]; then
|
|
35
|
+
client_id="$(tr -d '[:space:]' < "$anon_file" 2>/dev/null || true)"
|
|
36
|
+
fi
|
|
37
|
+
if [[ -z "$client_id" ]]; then
|
|
38
|
+
if command -v uuidgen >/dev/null 2>&1; then
|
|
39
|
+
client_id="$(uuidgen | tr '[:upper:]' '[:lower:]')"
|
|
40
|
+
else
|
|
41
|
+
client_id="$(od -An -N16 -tx1 /dev/urandom 2>/dev/null | tr -d ' \n')"
|
|
42
|
+
client_id="${client_id:0:8}-${client_id:8:4}-${client_id:12:4}-${client_id:16:4}-${client_id:20:12}"
|
|
43
|
+
fi
|
|
44
|
+
[[ -n "${HOME:-}" ]] && mkdir -p "${HOME}/.arize" 2>/dev/null || true
|
|
45
|
+
[[ -n "${HOME:-}" ]] && printf '%s' "$client_id" > "$anon_file" 2>/dev/null || true
|
|
46
|
+
fi
|
|
47
|
+
local body="{\"event\":\"$name\",\"anonymousId\":\"$client_id\"}"
|
|
48
|
+
if command -v curl >/dev/null 2>&1; then
|
|
49
|
+
curl -fsS -m 2 -X POST -H 'content-type: application/json' -d "$body" "$ANALYTICS_ENDPOINT" >/dev/null 2>&1 &
|
|
50
|
+
fi
|
|
51
|
+
}
|
|
25
52
|
# Where the bundled harness wheels live, same package. Override for testing.
|
|
26
53
|
VENDOR_URL="${ARIZE_VENDOR_URL:-https://cdn.jsdelivr.net/npm/evals/vendor}"
|
|
27
54
|
|
|
@@ -155,6 +182,7 @@ if [[ ! -t 1 ]]; then
|
|
|
155
182
|
CHOSEN=""
|
|
156
183
|
else
|
|
157
184
|
CHOSEN="$(choose_agent)" || exit 1
|
|
185
|
+
track_evals_event npx_evals_agent_selected
|
|
158
186
|
fi
|
|
159
187
|
|
|
160
188
|
# A directory, not a bare temp file: Step 4A looks for the offline bundle *beside*
|
|
@@ -186,7 +214,8 @@ clear_prompt_dir() {
|
|
|
186
214
|
for sub in "$1"/arize-offline "$1"/.staging*; do
|
|
187
215
|
[ -d "$sub" ] && clear_bundle_dir "$sub"
|
|
188
216
|
done
|
|
189
|
-
rm -f "$1/onboarding-prompt.md" "$1/harness.env"
|
|
217
|
+
rm -f "$1/onboarding-prompt.md" "$1/harness.env" "$1/.prompt-manifest" \
|
|
218
|
+
"$1/track-event.mjs" "$1/analytics.js"
|
|
190
219
|
# Anything left is not ours: bail out and let the caller fall back.
|
|
191
220
|
rmdir "$1" 2>/dev/null || { [ -z "$(ls -A "$1" 2>/dev/null)" ]; return $?; }
|
|
192
221
|
}
|
|
@@ -224,12 +253,65 @@ else
|
|
|
224
253
|
exit 1
|
|
225
254
|
fi
|
|
226
255
|
|
|
256
|
+
MANIFEST_FILE="$PROMPT_DIR/.prompt-manifest"
|
|
257
|
+
# This bootstrap verifies the prompt digest but cannot independently verify the
|
|
258
|
+
# manifest signature on every supported shell. Its trust root is TLS to jsDelivr.
|
|
227
259
|
echo "Fetching the onboarding prompt…"
|
|
260
|
+
if ! fetch "$PROMPT_MANIFEST_URL" "$MANIFEST_FILE"; then
|
|
261
|
+
echo "Failed to download the onboarding prompt manifest." >&2
|
|
262
|
+
echo "Check your connection and try again." >&2
|
|
263
|
+
exit 1
|
|
264
|
+
fi
|
|
265
|
+
|
|
266
|
+
manifest_value() {
|
|
267
|
+
values="$(sed -n "s/^[[:space:]]*\"$1\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\"[[:space:]]*,\{0,1\}[[:space:]]*$/\1/p" "$MANIFEST_FILE")"
|
|
268
|
+
[ "$(printf '%s\n' "$values" | sed '/^$/d' | wc -l | tr -d ' ')" -eq 1 ] || return 1
|
|
269
|
+
printf '%s' "$values"
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
PROMPT_URL="$(manifest_value prompt_url)" || { echo "The onboarding prompt manifest is invalid." >&2; exit 1; }
|
|
273
|
+
PROMPT_SHA256="$(manifest_value prompt_sha256)" || { echo "The onboarding prompt manifest is invalid." >&2; exit 1; }
|
|
274
|
+
rm -f "$MANIFEST_FILE"
|
|
275
|
+
if [ "${ARIZE_ALLOW_LOCAL_PROMPT_TEST:-}" = "1" ] \
|
|
276
|
+
&& [ -n "${ARIZE_PROMPT_MANIFEST_URL:-}" ]; then
|
|
277
|
+
case "$PROMPT_URL" in
|
|
278
|
+
http://127.0.0.1:*/onboarding-prompt.md) ;;
|
|
279
|
+
*) echo "The local prompt test URL must use 127.0.0.1 and onboarding-prompt.md." >&2; exit 1 ;;
|
|
280
|
+
esac
|
|
281
|
+
else
|
|
282
|
+
case "$PROMPT_URL" in
|
|
283
|
+
https://cdn.jsdelivr.net/npm/evals@*/onboarding-prompt.md) ;;
|
|
284
|
+
*) echo "The onboarding prompt manifest has an invalid prompt URL." >&2; exit 1 ;;
|
|
285
|
+
esac
|
|
286
|
+
fi
|
|
287
|
+
case "$PROMPT_SHA256" in
|
|
288
|
+
*[!0-9a-fA-F]*) echo "The onboarding prompt manifest has an invalid digest." >&2; exit 1 ;;
|
|
289
|
+
esac
|
|
290
|
+
if [ "${#PROMPT_SHA256}" -ne 64 ]; then
|
|
291
|
+
echo "The onboarding prompt manifest has an invalid digest." >&2
|
|
292
|
+
exit 1
|
|
293
|
+
fi
|
|
228
294
|
if ! fetch "$PROMPT_URL" "$PROMPT_FILE"; then
|
|
229
|
-
echo "Failed to download the onboarding prompt
|
|
295
|
+
echo "Failed to download the onboarding prompt." >&2
|
|
230
296
|
echo "Check your connection and try again." >&2
|
|
231
297
|
exit 1
|
|
232
298
|
fi
|
|
299
|
+
if command -v shasum >/dev/null 2>&1; then
|
|
300
|
+
ACTUAL_SHA256="$(shasum -a 256 "$PROMPT_FILE" | awk '{print $1}')"
|
|
301
|
+
elif command -v sha256sum >/dev/null 2>&1; then
|
|
302
|
+
ACTUAL_SHA256="$(sha256sum "$PROMPT_FILE" | awk '{print $1}')"
|
|
303
|
+
else
|
|
304
|
+
echo "Need shasum or sha256sum to verify the onboarding prompt." >&2
|
|
305
|
+
exit 1
|
|
306
|
+
fi
|
|
307
|
+
if [ "$ACTUAL_SHA256" != "$PROMPT_SHA256" ]; then
|
|
308
|
+
echo "The onboarding prompt digest did not match its manifest." >&2
|
|
309
|
+
exit 1
|
|
310
|
+
fi
|
|
311
|
+
|
|
312
|
+
# Best-effort: agent runs these before OAuth. Missing files just skip the ping.
|
|
313
|
+
fetch "$TRACK_URL" "$PROMPT_DIR/track-event.mjs" 2>/dev/null || true
|
|
314
|
+
fetch "$ANALYTICS_URL" "$PROMPT_DIR/analytics.js" 2>/dev/null || true
|
|
233
315
|
|
|
234
316
|
# Fetch the bundled tracing harness so Step 4A can install it without piping a
|
|
235
317
|
# downloaded script into a shell — the thing auto-approval permission classifiers
|
|
@@ -272,7 +354,7 @@ fi
|
|
|
272
354
|
|
|
273
355
|
# No "in this project": this may well be run from a home directory, and Step 4 is
|
|
274
356
|
# what scopes the work. Keep this wording in step with cli.js and start.ps1.
|
|
275
|
-
SEED="Read the file '$PROMPT_FILE' in full
|
|
357
|
+
SEED="Read the file '$PROMPT_FILE' in full before doing anything else. Prefer your file-reading tool. If none is available, use read-only shell commands with bounded line ranges solely to print this exact file, repeating with successive ranges until EOF. Do not inspect or change anything else, and do not invoke a skill until a step tells you to. Then follow its steps in order from Step 0, walking me through each step and asking me questions as needed."
|
|
276
358
|
|
|
277
359
|
if [[ -z "$CHOSEN" ]]; then
|
|
278
360
|
# Addressed to the person, two lines, recommendation first — see the note in cli.js.
|
package/track-event.mjs
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Fire one anon funnel event, then exit.
|
|
4
|
+
*
|
|
5
|
+
* Staged next to the onboarding prompt so the agent can run it before opening
|
|
6
|
+
* the Arize signup/sign-in browser (OAuth) without naming `npx evals`.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* node ~/.arize/onboarding/track-event.mjs auth-opened
|
|
10
|
+
*
|
|
11
|
+
* Always exits 0 — tracking must never block auth.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { trackEvent } from './analytics.js';
|
|
15
|
+
|
|
16
|
+
/** @type {Record<string, string>} */
|
|
17
|
+
const EVENTS = {
|
|
18
|
+
'auth-opened': 'npx_evals_auth_opened',
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {string[]} argv
|
|
23
|
+
* @returns {Promise<void>}
|
|
24
|
+
*/
|
|
25
|
+
export async function run(argv) {
|
|
26
|
+
const key = argv[0] || '';
|
|
27
|
+
const name = EVENTS[key];
|
|
28
|
+
if (!name) return;
|
|
29
|
+
|
|
30
|
+
await trackEvent(name);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const isDirect =
|
|
34
|
+
process.argv[1] &&
|
|
35
|
+
(process.argv[1].endsWith('track-event.mjs') ||
|
|
36
|
+
process.argv[1].endsWith('track-event'));
|
|
37
|
+
|
|
38
|
+
if (isDirect) {
|
|
39
|
+
run(process.argv.slice(2)).finally(() => process.exit(0));
|
|
40
|
+
}
|
package/vendor/MANIFEST
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
a9cede65f98d3415b13e1c6a437d0fdee27286bfff0186dd72bb65d9869b7864 LICENSE-coding-harness-tracing
|
|
2
2
|
62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775 certifi-2026.7.22-py3-none-any.whl
|
|
3
|
-
|
|
3
|
+
6fa310dbfb392719881f8c9459d9d2a61c958e39c4d0d4e9c4ac29c7cb7403ce coding_harness_tracing-0.1.0-py3-none-any.whl
|
|
4
4
|
aca14e09ca99c253d2a142e2d5c5c38c8c7cf90840d3cb10b241c29929871fa4 harness-install.bat
|
|
5
5
|
a7ba18a98280e236b20ab4cb9f8a4006068b454586a2af50bf23fb0dbe70583d harness-install.sh
|
|
6
6
|
b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61 python_dotenv-1.2.1-py3-none-any.whl
|
|
Binary file
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"repo": "https://github.com/Arize-ai/coding-harness-tracing",
|
|
3
3
|
"ref": "main",
|
|
4
|
-
"resolvedSha": "
|
|
4
|
+
"resolvedSha": "62609f080d6a6b4786114e45dafd90a2945f2233",
|
|
5
5
|
"source": "git",
|
|
6
6
|
"wheel": "coding_harness_tracing-0.1.0-py3-none-any.whl",
|
|
7
7
|
"wheelVersion": "0.1.0",
|
|
8
|
-
"wheelSha256": "
|
|
8
|
+
"wheelSha256": "6fa310dbfb392719881f8c9459d9d2a61c958e39c4d0d4e9c4ac29c7cb7403ce",
|
|
9
9
|
"files": [
|
|
10
10
|
"LICENSE-coding-harness-tracing",
|
|
11
11
|
"MANIFEST",
|