pairit 0.2.0 → 0.3.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 +7 -7
- package/dist/index.js +55 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,8 +43,8 @@ pairit login # Authenticate (required firs
|
|
|
43
43
|
|
|
44
44
|
pairit config lint path/to/config.yaml
|
|
45
45
|
pairit config compile path/to/config.yaml
|
|
46
|
-
pairit config upload configs/simple-survey-basic.yaml --
|
|
47
|
-
pairit config upload configs/agent-study.yaml --
|
|
46
|
+
pairit config upload configs/simple-survey-basic.yaml --name simple-survey-basic
|
|
47
|
+
pairit config upload configs/agent-study.yaml --name agent-study --openai-api-key sk-...
|
|
48
48
|
pairit config list
|
|
49
49
|
pairit config delete 2f3c4d5e...
|
|
50
50
|
|
|
@@ -66,8 +66,8 @@ Add `--private` if you need to keep an object private. Use `--bucket <name>` onl
|
|
|
66
66
|
# Point at local manager (published CLI defaults to production)
|
|
67
67
|
export PAIRIT_API_URL=http://localhost:3002
|
|
68
68
|
|
|
69
|
-
bun run apps/manager/cli/src/index.ts config upload configs/simple-survey-basic.yaml --
|
|
70
|
-
bun run apps/manager/cli/src/index.ts config upload configs/agent-study.yaml --
|
|
69
|
+
bun run apps/manager/cli/src/index.ts config upload configs/simple-survey-basic.yaml --name simple-survey-basic
|
|
70
|
+
bun run apps/manager/cli/src/index.ts config upload configs/agent-study.yaml --name agent-study --openai-api-key sk-...
|
|
71
71
|
bun run apps/manager/cli/src/index.ts config list
|
|
72
72
|
bun run apps/manager/cli/src/index.ts config delete 2f3c4d5e... --force
|
|
73
73
|
|
|
@@ -76,7 +76,7 @@ bun run apps/manager/cli/src/index.ts media list
|
|
|
76
76
|
bun run apps/manager/cli/src/index.ts media delete onboarding/logo.png --force
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
`config compile` writes `configs/simple-survey-basic.json` next to the source YAML. `config upload`
|
|
79
|
+
`config compile` writes `configs/simple-survey-basic.json` next to the source YAML. `config upload` creates or updates a config by name (`--name`, else the YAML `name:` field, else the file name). The server assigns the config id (`<name>-<10 random chars>`) on the first upload, and later uploads under the same name add revisions. `--config-id` updates an existing config by id. See `config history` for past revisions.
|
|
80
80
|
|
|
81
81
|
## Manager allowlist (admin)
|
|
82
82
|
|
|
@@ -101,8 +101,8 @@ Notes:
|
|
|
101
101
|
If your config uses AI agents, attach provider credentials when uploading:
|
|
102
102
|
|
|
103
103
|
```bash
|
|
104
|
-
pairit config upload path/to/config.yaml --
|
|
105
|
-
pairit config upload path/to/config.yaml --
|
|
104
|
+
pairit config upload path/to/config.yaml --name my-exp --openai-api-key sk-...
|
|
105
|
+
pairit config upload path/to/config.yaml --name my-exp --anthropic-api-key sk-ant-...
|
|
106
106
|
```
|
|
107
107
|
|
|
108
108
|
Notes:
|
package/dist/index.js
CHANGED
|
@@ -9805,7 +9805,7 @@ async function attachHtmlToCompiledConfig(configPath, compiled) {
|
|
|
9805
9805
|
|
|
9806
9806
|
// src/index.ts
|
|
9807
9807
|
var program2 = new Command;
|
|
9808
|
-
program2.name("pairit").description("CLI for Pairit experiment configs").version("0.
|
|
9808
|
+
program2.name("pairit").description("CLI for Pairit experiment configs").version("0.3.0").option("--env <name>", "Target environment: staging or production", (value) => {
|
|
9809
9809
|
try {
|
|
9810
9810
|
return parseEnvName(value);
|
|
9811
9811
|
} catch (error) {
|
|
@@ -9853,7 +9853,7 @@ configCommand.command("compile").argument("<config>", "Path to YAML config").des
|
|
|
9853
9853
|
process11.exitCode = 1;
|
|
9854
9854
|
}
|
|
9855
9855
|
});
|
|
9856
|
-
configCommand.command("upload").argument("<config>", "Path to YAML config").option("--config-id <configId>", "
|
|
9856
|
+
configCommand.command("upload").argument("<config>", "Path to YAML config").option("--name <name>", "Config name (defaults to the YAML name field, then the file name)").option("--config-id <configId>", "Update an existing config by id (configs created before names)").option("--metadata <json>", "Optional metadata JSON string").option("--openai-api-key <key>", "OpenAI API key for this experiment").option("--anthropic-api-key <key>", "Anthropic API key for this experiment").description("Compile and upload config via Pairit Functions").action(async (configPath, options) => {
|
|
9857
9857
|
try {
|
|
9858
9858
|
const { payload, checksum, attachments } = await buildUploadPayload(configPath, options);
|
|
9859
9859
|
const response = await callFunctions("/configs/upload", {
|
|
@@ -9864,10 +9864,23 @@ configCommand.command("upload").argument("<config>", "Path to YAML config").opti
|
|
|
9864
9864
|
for (const file of attachments) {
|
|
9865
9865
|
console.log(`✓ Attached ${path3.basename(file.src)} (${formatBytes(file.bytes)})`);
|
|
9866
9866
|
}
|
|
9867
|
-
|
|
9867
|
+
const result = response;
|
|
9868
|
+
const label = result.name ? `${result.name} (${result.configId})` : result.configId;
|
|
9869
|
+
if (result.created) {
|
|
9870
|
+
console.log(`✓ Created ${label}, revision ${result.revision}`);
|
|
9871
|
+
} else if (result.previousRevision != null) {
|
|
9872
|
+
console.log(`✓ Uploaded ${label}, revision ${result.previousRevision} → ${result.revision}`);
|
|
9873
|
+
} else {
|
|
9874
|
+
console.log(`✓ Uploaded ${label}, revision ${result.revision} (config unchanged)`);
|
|
9875
|
+
}
|
|
9876
|
+
console.log(` checksum ${checksum}`);
|
|
9877
|
+
if (result.previousRevision != null && result.previousRevisionSessionCount > 0) {
|
|
9878
|
+
const n = result.previousRevisionSessionCount;
|
|
9879
|
+
console.warn(`⚠ ${n} participant${n === 1 ? "" : "s"} ran revision ${result.previousRevision}. New participants will get revision ${result.revision}.`);
|
|
9880
|
+
console.warn(" Exports record each session's configRevision. For a different study, upload under a new --name instead.");
|
|
9881
|
+
}
|
|
9868
9882
|
const labUrl = getLabUrl();
|
|
9869
|
-
console.log(`Survey Link: ${labUrl}/${
|
|
9870
|
-
console.log(JSON.stringify(response, null, 2));
|
|
9883
|
+
console.log(`Survey Link: ${labUrl}/${result.configId}`);
|
|
9871
9884
|
} catch (error) {
|
|
9872
9885
|
reportCliError("Upload failed", error);
|
|
9873
9886
|
}
|
|
@@ -9883,12 +9896,41 @@ configCommand.command("list").description("List configs from Pairit Functions").
|
|
|
9883
9896
|
configs.forEach((config) => {
|
|
9884
9897
|
const metadata = config.metadata;
|
|
9885
9898
|
const filename = metadata?.originalFilename ? ` | file=${metadata.originalFilename}` : "";
|
|
9886
|
-
|
|
9899
|
+
const name = config.name ? `name=${config.name} | ` : "";
|
|
9900
|
+
const revision = config.revision != null ? ` | revision=${config.revision}` : "";
|
|
9901
|
+
console.log(`${name}configId=${config.configId}${revision} | owner=${config.owner} | checksum=${config.checksum}${filename} | updated=${config.updatedAt ?? "n/a"}`);
|
|
9887
9902
|
});
|
|
9888
9903
|
} catch (error) {
|
|
9889
9904
|
reportCliError("List failed", error);
|
|
9890
9905
|
}
|
|
9891
9906
|
});
|
|
9907
|
+
configCommand.command("history").argument("<configId>", "Config id").option("--revision <n>", "Download one revision's compiled config").option("--out <file>", "With --revision, write the config to this file").description("List a config's revisions, or download one").action(async (configId, options) => {
|
|
9908
|
+
try {
|
|
9909
|
+
const base = `/configs/${encodeURIComponent(configId)}/revisions`;
|
|
9910
|
+
if (options.revision) {
|
|
9911
|
+
const revision = await callFunctions(`${base}/${encodeURIComponent(options.revision)}`, { method: "GET" });
|
|
9912
|
+
const json = JSON.stringify(revision.config, null, 2);
|
|
9913
|
+
if (options.out) {
|
|
9914
|
+
await writeFile2(options.out, json, "utf8");
|
|
9915
|
+
console.log(`✓ Wrote revision ${options.revision} to ${options.out}`);
|
|
9916
|
+
} else {
|
|
9917
|
+
console.log(json);
|
|
9918
|
+
}
|
|
9919
|
+
return;
|
|
9920
|
+
}
|
|
9921
|
+
const history = await callFunctions(base, { method: "GET" });
|
|
9922
|
+
if (!history.revisions.length) {
|
|
9923
|
+
console.log("No revisions recorded yet. They start with the next upload.");
|
|
9924
|
+
return;
|
|
9925
|
+
}
|
|
9926
|
+
for (const r of history.revisions) {
|
|
9927
|
+
const current = r.revision === history.currentRevision ? " (current)" : "";
|
|
9928
|
+
console.log(`revision=${r.revision}${current} | sessions=${r.sessionCount} | uploaded=${r.createdAt ?? "n/a"} | checksum=${r.checksum ?? "n/a"}`);
|
|
9929
|
+
}
|
|
9930
|
+
} catch (error) {
|
|
9931
|
+
reportCliError("History failed", error);
|
|
9932
|
+
}
|
|
9933
|
+
});
|
|
9892
9934
|
configCommand.command("delete").argument("<configId>", "Config id to delete").option("--force", "Skip confirmation").description("Delete config via Pairit Functions").action(async (configId, options) => {
|
|
9893
9935
|
try {
|
|
9894
9936
|
if (!options.force) {
|
|
@@ -10033,6 +10075,9 @@ async function lintConfig(configPath) {
|
|
|
10033
10075
|
if (!config.schema_version) {
|
|
10034
10076
|
errors.push("missing schema_version");
|
|
10035
10077
|
}
|
|
10078
|
+
if (config.name !== undefined && (typeof config.name !== "string" || !config.name.trim())) {
|
|
10079
|
+
errors.push("name must be a non-empty string");
|
|
10080
|
+
}
|
|
10036
10081
|
if (!config.initialPageId) {
|
|
10037
10082
|
errors.push("missing initialPageId");
|
|
10038
10083
|
}
|
|
@@ -10115,7 +10160,8 @@ async function buildUploadPayload(configPath, options) {
|
|
|
10115
10160
|
const attachments = await attachHtmlToCompiledConfig(configPath, parsed);
|
|
10116
10161
|
const hashBuffer = createHash("sha256").update(JSON.stringify(parsed)).digest();
|
|
10117
10162
|
const checksum = hashBuffer.toString("hex");
|
|
10118
|
-
const
|
|
10163
|
+
const explicitName = options.name ?? sourceConfig.name;
|
|
10164
|
+
const name = options.configId ? explicitName : explicitName ?? path3.basename(configPath, path3.extname(configPath));
|
|
10119
10165
|
const metadata = options.metadata ? JSON.parse(options.metadata) : {};
|
|
10120
10166
|
if (!metadata.originalFilename) {
|
|
10121
10167
|
metadata.originalFilename = path3.basename(configPath);
|
|
@@ -10128,7 +10174,8 @@ async function buildUploadPayload(configPath, options) {
|
|
|
10128
10174
|
};
|
|
10129
10175
|
return {
|
|
10130
10176
|
payload: {
|
|
10131
|
-
|
|
10177
|
+
...name && { name },
|
|
10178
|
+
...options.configId && { configId: options.configId },
|
|
10132
10179
|
checksum,
|
|
10133
10180
|
metadata: metadata ?? null,
|
|
10134
10181
|
config: parsed,
|