@madewithremy/admin 0.1.31 → 0.1.33
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/dist/index.d.ts +129 -19
- package/dist/index.js +31 -13
- package/dist/index.js.map +1 -1
- package/dist/prod.js +258 -76
- package/package.json +1 -1
package/dist/prod.js
CHANGED
|
@@ -1019,13 +1019,6 @@ async function dashboardLive(ctx) {
|
|
|
1019
1019
|
);
|
|
1020
1020
|
return dashboard.liveRelease;
|
|
1021
1021
|
}
|
|
1022
|
-
function buildFailureReason(release) {
|
|
1023
|
-
const log = Array.isArray(release.buildLog) ? release.buildLog : [];
|
|
1024
|
-
const errors = log.filter(
|
|
1025
|
-
(entry) => entry?.phase === "error" && typeof entry.message === "string"
|
|
1026
|
-
);
|
|
1027
|
-
return errors.length ? errors[errors.length - 1].message : null;
|
|
1028
|
-
}
|
|
1029
1022
|
function summarizeRelease(release) {
|
|
1030
1023
|
const summary2 = {
|
|
1031
1024
|
releaseId: release.id,
|
|
@@ -1048,7 +1041,7 @@ function summarizeRelease(release) {
|
|
|
1048
1041
|
}
|
|
1049
1042
|
return {
|
|
1050
1043
|
...summary2,
|
|
1051
|
-
error: release.failureReason ??
|
|
1044
|
+
error: release.failureReason ?? "Build failed (no error entry in the build log)",
|
|
1052
1045
|
...release.failureKind ? { failureKind: release.failureKind } : {},
|
|
1053
1046
|
...release.failurePhase ? { failurePhase: release.failurePhase } : {}
|
|
1054
1047
|
};
|
|
@@ -2946,7 +2939,7 @@ var filesSpecs = {
|
|
|
2946
2939
|
usage: "Usage: remy-admin files list"
|
|
2947
2940
|
},
|
|
2948
2941
|
"files rm": {
|
|
2949
|
-
usage: "Usage: remy-admin files rm --store <name> --key <key> [--private]",
|
|
2942
|
+
usage: "Usage: remy-admin files rm --store <name> --key <key> [--public|--private]",
|
|
2950
2943
|
flags: {
|
|
2951
2944
|
...ACCESS_FLAGS,
|
|
2952
2945
|
store: { type: "string" },
|
|
@@ -2957,6 +2950,45 @@ var filesSpecs = {
|
|
|
2957
2950
|
function resolveAccess(a) {
|
|
2958
2951
|
return a.bool("private") ? "private" : "public";
|
|
2959
2952
|
}
|
|
2953
|
+
async function readAccess(ctx, a, key) {
|
|
2954
|
+
if (a.bool("private")) {
|
|
2955
|
+
return "private";
|
|
2956
|
+
}
|
|
2957
|
+
if (a.bool("public")) {
|
|
2958
|
+
return "public";
|
|
2959
|
+
}
|
|
2960
|
+
const store = storeOf(a);
|
|
2961
|
+
const { stores } = await summary(ctx);
|
|
2962
|
+
const held = stores.filter((s) => s.store === store && s.objectCount > 0);
|
|
2963
|
+
if (held.length === 1) {
|
|
2964
|
+
return held[0].access;
|
|
2965
|
+
}
|
|
2966
|
+
if (held.length === 0) {
|
|
2967
|
+
if (key === void 0) {
|
|
2968
|
+
return "public";
|
|
2969
|
+
}
|
|
2970
|
+
fatal(`Store "${store}" holds no objects, public or private.`);
|
|
2971
|
+
}
|
|
2972
|
+
if (key === void 0) {
|
|
2973
|
+
const counts = held.map((s) => `${s.objectCount.toLocaleString()} ${s.access}`).join(", ");
|
|
2974
|
+
fatal(
|
|
2975
|
+
`Store "${store}" holds objects in both halves (${counts}): pass --public or --private.`
|
|
2976
|
+
);
|
|
2977
|
+
}
|
|
2978
|
+
for (const access of ["private", "public"]) {
|
|
2979
|
+
try {
|
|
2980
|
+
await stat(ctx, { store, access, key });
|
|
2981
|
+
return access;
|
|
2982
|
+
} catch (err) {
|
|
2983
|
+
if (!(err instanceof AdminApiError) || err.status !== 404) {
|
|
2984
|
+
throw err;
|
|
2985
|
+
}
|
|
2986
|
+
}
|
|
2987
|
+
}
|
|
2988
|
+
fatal(
|
|
2989
|
+
`No object "${key}" in store "${store}" (looked in its private and public halves).`
|
|
2990
|
+
);
|
|
2991
|
+
}
|
|
2960
2992
|
function storeOf(a) {
|
|
2961
2993
|
return a.str("store") || DEFAULT_STORE;
|
|
2962
2994
|
}
|
|
@@ -2967,8 +2999,8 @@ function requireKeyFlag(a) {
|
|
|
2967
2999
|
}
|
|
2968
3000
|
return key;
|
|
2969
3001
|
}
|
|
2970
|
-
function refOf(a, key) {
|
|
2971
|
-
return { store: storeOf(a), access:
|
|
3002
|
+
async function refOf(ctx, a, key) {
|
|
3003
|
+
return { store: storeOf(a), access: await readAccess(ctx, a, key), key };
|
|
2972
3004
|
}
|
|
2973
3005
|
async function filesPut(ctx, a) {
|
|
2974
3006
|
const file = a.req("file");
|
|
@@ -2994,7 +3026,7 @@ async function filesPut(ctx, a) {
|
|
|
2994
3026
|
}
|
|
2995
3027
|
async function filesGet(ctx, a) {
|
|
2996
3028
|
const key = a.req("key");
|
|
2997
|
-
const ref = refOf(a, key);
|
|
3029
|
+
const ref = await refOf(ctx, a, key);
|
|
2998
3030
|
const { url } = await sign(
|
|
2999
3031
|
ctx,
|
|
3000
3032
|
ref,
|
|
@@ -3004,7 +3036,9 @@ async function filesGet(ctx, a) {
|
|
|
3004
3036
|
const abs = path2.isAbsolute(outPath) ? outPath : path2.join(WORKSPACE_DIR, outPath);
|
|
3005
3037
|
const res = await fetch(url);
|
|
3006
3038
|
if (!res.ok || !res.body) {
|
|
3007
|
-
fatal(
|
|
3039
|
+
fatal(
|
|
3040
|
+
res.status === 403 || res.status === 404 ? `No object "${key}" in the ${ref.access} half of store "${ref.store}" (download answered ${res.status}).` : `Download failed: ${res.status} ${res.statusText}`
|
|
3041
|
+
);
|
|
3008
3042
|
}
|
|
3009
3043
|
await pipeline(
|
|
3010
3044
|
Readable.fromWeb(res.body),
|
|
@@ -3013,16 +3047,18 @@ async function filesGet(ctx, a) {
|
|
|
3013
3047
|
out({ path: abs, size: fs2.statSync(abs).size });
|
|
3014
3048
|
}
|
|
3015
3049
|
async function filesSign(ctx, a) {
|
|
3016
|
-
out(
|
|
3050
|
+
out(
|
|
3051
|
+
await sign(ctx, await refOf(ctx, a, requireKeyFlag(a)), a.num("ttl"))
|
|
3052
|
+
);
|
|
3017
3053
|
}
|
|
3018
3054
|
async function filesStat(ctx, a) {
|
|
3019
|
-
out(await stat(ctx, refOf(a, requireKeyFlag(a))));
|
|
3055
|
+
out(await stat(ctx, await refOf(ctx, a, requireKeyFlag(a))));
|
|
3020
3056
|
}
|
|
3021
3057
|
async function filesLs(ctx, a) {
|
|
3022
3058
|
out(
|
|
3023
3059
|
await ls(ctx, {
|
|
3024
3060
|
store: storeOf(a),
|
|
3025
|
-
access:
|
|
3061
|
+
access: await readAccess(ctx, a),
|
|
3026
3062
|
prefix: a.str("prefix"),
|
|
3027
3063
|
q: a.str("q"),
|
|
3028
3064
|
cursor: a.str("cursor"),
|
|
@@ -3042,7 +3078,13 @@ async function filesRm(ctx, a) {
|
|
|
3042
3078
|
if (!key) {
|
|
3043
3079
|
fatal("--key is required.");
|
|
3044
3080
|
}
|
|
3045
|
-
out(
|
|
3081
|
+
out(
|
|
3082
|
+
await remove(ctx, {
|
|
3083
|
+
store,
|
|
3084
|
+
access: await readAccess(ctx, a, key),
|
|
3085
|
+
key
|
|
3086
|
+
})
|
|
3087
|
+
);
|
|
3046
3088
|
}
|
|
3047
3089
|
var filesHandlers = {
|
|
3048
3090
|
"files put": filesPut,
|
|
@@ -3066,12 +3108,12 @@ Subcommands:
|
|
|
3066
3108
|
|
|
3067
3109
|
Usage:
|
|
3068
3110
|
remy-admin files put [--public|--private] [--store <name>] [--key <key>] [--cache-control <value>] <file>
|
|
3069
|
-
remy-admin files get [--private] [--store <name>] [--out <path>] <key>
|
|
3070
|
-
remy-admin files sign [--private] [--store <name>] [--ttl <seconds>] --key <key>
|
|
3071
|
-
remy-admin files stat [--private] [--store <name>] --key <key>
|
|
3072
|
-
remy-admin files ls [--private] [--store <name>] [--prefix <prefix>] [--q <substring>] [--limit <n>]
|
|
3111
|
+
remy-admin files get [--public|--private] [--store <name>] [--out <path>] <key>
|
|
3112
|
+
remy-admin files sign [--public|--private] [--store <name>] [--ttl <seconds>] --key <key>
|
|
3113
|
+
remy-admin files stat [--public|--private] [--store <name>] --key <key>
|
|
3114
|
+
remy-admin files ls [--public|--private] [--store <name>] [--prefix <prefix>] [--q <substring>] [--limit <n>]
|
|
3073
3115
|
remy-admin files list
|
|
3074
|
-
remy-admin files rm --store <name> --key <key> [--private]
|
|
3116
|
+
remy-admin files rm --store <name> --key <key> [--public|--private]
|
|
3075
3117
|
|
|
3076
3118
|
Examples:
|
|
3077
3119
|
remy-admin files put --public ./hero.jpg
|
|
@@ -3081,7 +3123,10 @@ Examples:
|
|
|
3081
3123
|
remy-admin files rm --store handoff --key <key> --private
|
|
3082
3124
|
|
|
3083
3125
|
Notes:
|
|
3084
|
-
- Defaults to
|
|
3126
|
+
- Defaults to the store named 'assets'. put writes public unless --private.
|
|
3127
|
+
Reads (get, sign, stat, ls, rm) without --public or --private use the half
|
|
3128
|
+
of the store that holds objects; in a store holding both, a key is found
|
|
3129
|
+
wherever it is, and ls asks which.
|
|
3085
3130
|
- Handing someone a large or sensitive file? Use a PRIVATE store + \`sign\`:
|
|
3086
3131
|
the link is unguessable, expires (--ttl seconds, max 7 days), and the object
|
|
3087
3132
|
stays deletable with \`rm\`. Never use the account media CDN
|
|
@@ -3119,6 +3164,7 @@ var summarize = (d) => ({
|
|
|
3119
3164
|
});
|
|
3120
3165
|
async function addDocument(ctx, params) {
|
|
3121
3166
|
const { slug, filename, content, metadata, entities: entities2, onProgress } = params;
|
|
3167
|
+
const { budgetDollars } = params;
|
|
3122
3168
|
const contentHash = createHash2("sha256").update(content).digest("hex");
|
|
3123
3169
|
const token = await call(
|
|
3124
3170
|
ctx,
|
|
@@ -3134,11 +3180,13 @@ async function addDocument(ctx, params) {
|
|
|
3134
3180
|
);
|
|
3135
3181
|
if (token.alreadyCurrent) {
|
|
3136
3182
|
onProgress?.(`${filename}: unchanged, skipped`);
|
|
3183
|
+
const documents3 = token.documents ?? [token.document];
|
|
3137
3184
|
return {
|
|
3138
3185
|
filename,
|
|
3139
3186
|
skipped: true,
|
|
3140
3187
|
document: token.document,
|
|
3141
|
-
documents:
|
|
3188
|
+
documents: documents3,
|
|
3189
|
+
documentCount: token.documentCount ?? documents3.length
|
|
3142
3190
|
};
|
|
3143
3191
|
}
|
|
3144
3192
|
onProgress?.(
|
|
@@ -3156,16 +3204,21 @@ async function addDocument(ctx, params) {
|
|
|
3156
3204
|
contentType: token.contentType,
|
|
3157
3205
|
size: content.length,
|
|
3158
3206
|
...metadata ? { metadata } : {},
|
|
3159
|
-
...entities2 ? { entities: entities2 } : {}
|
|
3207
|
+
...entities2 ? { entities: entities2 } : {},
|
|
3208
|
+
...budgetDollars !== void 0 ? { budgetDollars } : {}
|
|
3160
3209
|
}
|
|
3161
3210
|
);
|
|
3211
|
+
const documents2 = confirmed.documents ?? (confirmed.document ? [confirmed.document] : []);
|
|
3162
3212
|
return {
|
|
3163
3213
|
filename,
|
|
3164
3214
|
skipped: false,
|
|
3165
3215
|
queued: confirmed.queued,
|
|
3166
3216
|
document: confirmed.document,
|
|
3167
|
-
documents:
|
|
3168
|
-
|
|
3217
|
+
documents: documents2,
|
|
3218
|
+
documentCount: confirmed.documentCount ?? documents2.length,
|
|
3219
|
+
outcome: confirmed.outcome,
|
|
3220
|
+
invalid: confirmed.invalid ?? null,
|
|
3221
|
+
job: confirmed.job ?? null
|
|
3169
3222
|
};
|
|
3170
3223
|
}
|
|
3171
3224
|
async function waitForIngest(ctx, params) {
|
|
@@ -3347,6 +3400,21 @@ function entities(ctx, params) {
|
|
|
3347
3400
|
}
|
|
3348
3401
|
);
|
|
3349
3402
|
}
|
|
3403
|
+
function passages(ctx, params) {
|
|
3404
|
+
const { slug, filter, cursor, limit, candidate } = params;
|
|
3405
|
+
return call(
|
|
3406
|
+
ctx,
|
|
3407
|
+
"POST",
|
|
3408
|
+
`${base(ctx.appId)}/passages`,
|
|
3409
|
+
{
|
|
3410
|
+
slug,
|
|
3411
|
+
...filter ? { filter } : {},
|
|
3412
|
+
...cursor ? { cursor } : {},
|
|
3413
|
+
...limit !== void 0 ? { limit } : {},
|
|
3414
|
+
...candidate ? { candidate: true } : {}
|
|
3415
|
+
}
|
|
3416
|
+
);
|
|
3417
|
+
}
|
|
3350
3418
|
function configGet(ctx, slug) {
|
|
3351
3419
|
return call(
|
|
3352
3420
|
ctx,
|
|
@@ -4870,12 +4938,14 @@ Dictionary:
|
|
|
4870
4938
|
background (a relink; \`dictionary status\` shows it), with nothing
|
|
4871
4939
|
re-embedded. An unchanged dictionary commits nothing.
|
|
4872
4940
|
|
|
4873
|
-
Matching ignores case and a tag's separators (P-101A, P101A, p 101a)
|
|
4941
|
+
Matching ignores case and a tag's separators (P-101A, P101A, p 101a) and
|
|
4942
|
+
an inch or foot mark after a size (8"-P-1057-A1A is 8-P-1057-A1A), takes
|
|
4874
4943
|
whole words only (P-101AB is not P-101A), and prefers the longest name; a
|
|
4875
4944
|
name two ids claim tags both. A name needs three letters or digits (two in
|
|
4876
4945
|
Chinese, Japanese or Korean). The push reports ambiguous names, the most
|
|
4877
|
-
claimed, and names that can't match their
|
|
4878
|
-
(\`unmatchable\`). Up to 250,000 entries, 16 names
|
|
4946
|
+
claimed (each with one name as pushed), and names that can't match their
|
|
4947
|
+
own text as written (\`unmatchable\`). Up to 250,000 entries, 16 names
|
|
4948
|
+
each, a million names.
|
|
4879
4949
|
|
|
4880
4950
|
\`link\` shows what the current dictionary finds in any text: check one
|
|
4881
4951
|
there before relying on it. --linker-version moves a dictionary to a newer
|
|
@@ -5179,7 +5249,8 @@ function mapTest(ctx, params) {
|
|
|
5179
5249
|
...selectionBody(params.selection),
|
|
5180
5250
|
...params.keys ? { keys: params.keys } : {},
|
|
5181
5251
|
...params.limit !== void 0 ? { limit: params.limit } : {},
|
|
5182
|
-
...params.dev ? { dev: true } : {}
|
|
5252
|
+
...params.dev ? { dev: true } : {},
|
|
5253
|
+
...params.releaseId ? { releaseId: params.releaseId } : {}
|
|
5183
5254
|
}
|
|
5184
5255
|
);
|
|
5185
5256
|
}
|
|
@@ -5245,12 +5316,13 @@ var dataSourceMappersSpecs = {
|
|
|
5245
5316
|
}
|
|
5246
5317
|
},
|
|
5247
5318
|
"datasources map test": {
|
|
5248
|
-
usage: "Usage: remy-admin datasources map test [--source <slug>] (--store <name> [--access <private|public>] [--prefix <p>] | --connector) [--keys k1,k2,...] [--limit <n>] [--dev] [--full]",
|
|
5319
|
+
usage: "Usage: remy-admin datasources map test [--source <slug>] (--store <name> [--access <private|public>] [--prefix <p>] | --connector) [--keys k1,k2,...] [--limit <n>] [--dev [--release <dev-release-id>]] [--full]",
|
|
5249
5320
|
flags: {
|
|
5250
5321
|
source: { type: "string" },
|
|
5251
5322
|
...SELECTION_FLAGS,
|
|
5252
5323
|
limit: { type: "number", min: 1 },
|
|
5253
5324
|
dev: { type: "boolean" },
|
|
5325
|
+
release: { type: "string" },
|
|
5254
5326
|
full: { type: "boolean" }
|
|
5255
5327
|
},
|
|
5256
5328
|
requireAnyOf: {
|
|
@@ -5362,7 +5434,8 @@ async function mapTest2(ctx, a) {
|
|
|
5362
5434
|
selection: selectionOf(a),
|
|
5363
5435
|
...keysOf(a) ? { keys: keysOf(a) } : {},
|
|
5364
5436
|
...limit !== void 0 ? { limit } : {},
|
|
5365
|
-
...a.bool("dev") ? { dev: true } : {}
|
|
5437
|
+
...a.bool("dev") ? { dev: true } : {},
|
|
5438
|
+
...a.str("release") ? { releaseId: a.str("release") } : {}
|
|
5366
5439
|
});
|
|
5367
5440
|
const results = a.bool("full") ? result.results : result.results.map(
|
|
5368
5441
|
(r) => r.outcome.kind === "documents" ? {
|
|
@@ -5496,7 +5569,7 @@ var dataSourceMappersHandlers = {
|
|
|
5496
5569
|
var dataSourceMappersHelp = `
|
|
5497
5570
|
Mapping raw objects into documents (mappers):
|
|
5498
5571
|
remy-admin datasources inspect [--source <slug>] (--store <name> [--prefix <p>] | --connector) [--keys k1,k2] [--limit <n>]
|
|
5499
|
-
remy-admin datasources map test [--source <slug>] (--store <name> [--prefix <p>] | --connector) [--keys k1,k2] [--limit <n>] [--dev] [--full]
|
|
5572
|
+
remy-admin datasources map test [--source <slug>] (--store <name> [--prefix <p>] | --connector) [--keys k1,k2] [--limit <n>] [--dev [--release <id>]] [--full]
|
|
5500
5573
|
remy-admin datasources map deploy [--source <slug>] [--release <id>]
|
|
5501
5574
|
remy-admin datasources remap [--source <slug>] [--budget <dollars>] [--limit <n>] [--wait] [--timeout <sec>]
|
|
5502
5575
|
remy-admin datasources jobs quarantine <id> [--kind skip|error] [--stage map|read] [--reason <text>] [--cursor <id>] [--limit <n>]
|
|
@@ -5511,14 +5584,21 @@ Mapping raw objects into documents (mappers):
|
|
|
5511
5584
|
map(object) reads the raw object (object.key, .bytes(), .text(), .json())
|
|
5512
5585
|
and answers documents([{ externalId, title, markdown, metadata?, replaces? }]),
|
|
5513
5586
|
passthrough() (ingest the raw object as-is), skip(reason) or
|
|
5514
|
-
deletes([externalId, ...]); throwing is the object's error.
|
|
5515
|
-
|
|
5516
|
-
|
|
5587
|
+
deletes([externalId, ...]); throwing is the object's error. documents()
|
|
5588
|
+
takes an array or any iterable, with no cap: the platform stores what it
|
|
5589
|
+
produces as it goes, so a generator yielding a document per row streams an
|
|
5590
|
+
export of any size. It may call models or fetch \u2014 every call is spend per
|
|
5591
|
+
object. Everything entering
|
|
5592
|
+
a mapped source is mapped: jobs, syncs and Source.add() alike; an add() of
|
|
5593
|
+
an object mapping to more than a thousand documents registers the first
|
|
5594
|
+
thousand and hands the rest to a job (\`datasources add --budget\` caps it).
|
|
5517
5595
|
|
|
5518
5596
|
The loop: \`inspect\` profiles the objects (key shapes, extensions, sizes,
|
|
5519
5597
|
JSON key signatures of ten sampled heads) before a line is written;
|
|
5520
5598
|
\`map test --dev\` runs the LOCAL mapper through the running dev session
|
|
5521
|
-
over real objects and prints every outcome without ingesting anything
|
|
5599
|
+
over real objects and prints every outcome without ingesting anything
|
|
5600
|
+
(each object's count, its first documents, and every document that fails
|
|
5601
|
+
validation, by its place in the mapper's output);
|
|
5522
5602
|
push a branch and wait for its build (\`releases wait\`) \u2014 a mapper runs on
|
|
5523
5603
|
the platform, so the platform has to compile it, and a private branch
|
|
5524
5604
|
build is all it needs; \`map deploy\` makes that build's mapper the
|
|
@@ -5537,7 +5617,11 @@ Mapping raw objects into documents (mappers):
|
|
|
5537
5617
|
ids this document supersedes (a writethru's original); deletes([...])
|
|
5538
5618
|
removes by id. A plan on a mapped source records the mapper's outcome mix
|
|
5539
5619
|
on its sample; a run whose skip share climbs past twice that (floor 5%)
|
|
5540
|
-
pauses with pauseReason 'skips' for a look at the quarantine.
|
|
5620
|
+
pauses with pauseReason 'skips' for a look at the quarantine. Documents
|
|
5621
|
+
that fail validation are left out and their object gets one quarantine row
|
|
5622
|
+
naming them; the rest register. A mapper built with an older
|
|
5623
|
+
@mindstudio-ai/agent, which returns documents inline, errors every
|
|
5624
|
+
documents outcome until it is upgraded, pushed and map deployed.
|
|
5541
5625
|
`;
|
|
5542
5626
|
|
|
5543
5627
|
// src/ops/dataSourceReaders.ts
|
|
@@ -5552,7 +5636,8 @@ function readerTest(ctx, params) {
|
|
|
5552
5636
|
{
|
|
5553
5637
|
slug: params.slug,
|
|
5554
5638
|
...params.documents ? { documents: params.documents } : {},
|
|
5555
|
-
...params.limit !== void 0 ? { limit: params.limit } : {}
|
|
5639
|
+
...params.limit !== void 0 ? { limit: params.limit } : {},
|
|
5640
|
+
...params.releaseId ? { releaseId: params.releaseId } : {}
|
|
5556
5641
|
}
|
|
5557
5642
|
);
|
|
5558
5643
|
}
|
|
@@ -5593,12 +5678,13 @@ function reread(ctx, params) {
|
|
|
5593
5678
|
// src/commands/dataSourceReaders.ts
|
|
5594
5679
|
var dataSourceReadersSpecs = {
|
|
5595
5680
|
"datasources reader test": {
|
|
5596
|
-
usage: "Usage: remy-admin datasources reader test --dev [--source <slug>] [--documents id1,id2,...] [--limit <n>]",
|
|
5681
|
+
usage: "Usage: remy-admin datasources reader test --dev [--source <slug>] [--documents id1,id2,...] [--limit <n>] [--release <dev-release-id>]",
|
|
5597
5682
|
flags: {
|
|
5598
5683
|
source: { type: "string" },
|
|
5599
5684
|
dev: { type: "boolean" },
|
|
5600
5685
|
documents: { type: "string" },
|
|
5601
|
-
limit: { type: "number", min: 1 }
|
|
5686
|
+
limit: { type: "number", min: 1 },
|
|
5687
|
+
release: { type: "string" }
|
|
5602
5688
|
}
|
|
5603
5689
|
},
|
|
5604
5690
|
"datasources reader status": {
|
|
@@ -5643,7 +5729,8 @@ async function readerTest2(ctx, a) {
|
|
|
5643
5729
|
const result = await readerTest(ctx, {
|
|
5644
5730
|
slug,
|
|
5645
5731
|
...documents2 ? { documents: documents2 } : {},
|
|
5646
|
-
...limit !== void 0 ? { limit } : {}
|
|
5732
|
+
...limit !== void 0 ? { limit } : {},
|
|
5733
|
+
...a.str("release") ? { releaseId: a.str("release") } : {}
|
|
5647
5734
|
});
|
|
5648
5735
|
out({
|
|
5649
5736
|
dataSource: slug,
|
|
@@ -5714,7 +5801,7 @@ var dataSourceReadersHandlers = {
|
|
|
5714
5801
|
};
|
|
5715
5802
|
var dataSourceReadersHelp = `
|
|
5716
5803
|
Reading documents into the app (readers):
|
|
5717
|
-
remy-admin datasources reader test --dev [--source <slug>] [--documents id1,id2] [--limit <n>]
|
|
5804
|
+
remy-admin datasources reader test --dev [--source <slug>] [--documents id1,id2] [--limit <n>] [--release <id>]
|
|
5718
5805
|
remy-admin datasources reader status [--source <slug>]
|
|
5719
5806
|
remy-admin datasources reader retry [--source <slug>] [--job <id>]
|
|
5720
5807
|
remy-admin datasources reread [--source <slug>] [--unread] [--filter <k=v|json>] [--budget <dollars>] [--limit <n>] [--wait] [--timeout <sec>]
|
|
@@ -5725,12 +5812,15 @@ Reading documents into the app (readers):
|
|
|
5725
5812
|
platform's batching, retries, budgets and pauses. Declare it in
|
|
5726
5813
|
mindstudio.json:
|
|
5727
5814
|
"dataSources": [{ "slug": "archive", "reader": { "path": "dist/datasources/archive.reader.ts" } }]
|
|
5728
|
-
The file exports defineReader(Archive, { read, removed, cleared
|
|
5729
|
-
@mindstudio-ai/agent. read(document) gets the document
|
|
5730
|
-
filename, metadata, entities)
|
|
5731
|
-
indexed with each one's entities
|
|
5732
|
-
|
|
5733
|
-
|
|
5815
|
+
The file exports defineReader(Archive, { read, removed, cleared?,
|
|
5816
|
+
relinked? }) from @mindstudio-ai/agent. read(document) gets the document
|
|
5817
|
+
(id, sourceId, filename, metadata, entities, url), document.chunks(), its
|
|
5818
|
+
passages as indexed with each one's entities, and document.bytes(), the
|
|
5819
|
+
file it came from; removed(documentId) is called when a document leaves
|
|
5820
|
+
the source; cleared(sourceId) once when the source is deleted; relinked(
|
|
5821
|
+
document) when a new dictionary re-tagged a document already read, for
|
|
5822
|
+
rows derived from its tags. Throwing fails that document, which is
|
|
5823
|
+
retried. A document can be
|
|
5734
5824
|
read more than once, so read() replaces the document's rows as a set,
|
|
5735
5825
|
keyed by its id, and removed() deletes them. Options on the declaration:
|
|
5736
5826
|
timeoutMs (per document, default 60000, max 300000) and concurrency
|
|
@@ -5792,12 +5882,13 @@ var CONFIG_FLAGS = {
|
|
|
5792
5882
|
};
|
|
5793
5883
|
var dataSourcesSpecs = {
|
|
5794
5884
|
"datasources add": {
|
|
5795
|
-
usage: "Usage: remy-admin datasources add [--source <slug>] [--metadata <k=v,...>] [--entities <id,...>] [--wait] [--timeout <sec>] <file...>",
|
|
5885
|
+
usage: "Usage: remy-admin datasources add [--source <slug>] [--metadata <k=v,...>] [--entities <id,...>] [--budget <dollars>] [--wait] [--timeout <sec>] <file...>",
|
|
5796
5886
|
positionals: [{ name: "file", required: true, variadic: true }],
|
|
5797
5887
|
flags: {
|
|
5798
5888
|
source: { type: "string" },
|
|
5799
5889
|
metadata: { type: "string" },
|
|
5800
5890
|
entities: { type: "string" },
|
|
5891
|
+
budget: { type: "number", min: 0.01 },
|
|
5801
5892
|
wait: { type: "boolean" },
|
|
5802
5893
|
timeout: { type: "string" }
|
|
5803
5894
|
}
|
|
@@ -5885,6 +5976,19 @@ var dataSourcesSpecs = {
|
|
|
5885
5976
|
candidate: { type: "boolean" }
|
|
5886
5977
|
}
|
|
5887
5978
|
},
|
|
5979
|
+
"datasources passages": {
|
|
5980
|
+
usage: "Usage: remy-admin datasources passages [--source <slug>] [--filter <k=v,...|json>] [--entities <id,...>] [--contains <words>] [--phrase <text>] [--cursor <cursor>] [--limit <n>] [--candidate]",
|
|
5981
|
+
flags: {
|
|
5982
|
+
source: { type: "string" },
|
|
5983
|
+
filter: { type: "string" },
|
|
5984
|
+
entities: { type: "string" },
|
|
5985
|
+
contains: { type: "string" },
|
|
5986
|
+
phrase: { type: "string" },
|
|
5987
|
+
cursor: { type: "string" },
|
|
5988
|
+
limit: { type: "number", min: 1 },
|
|
5989
|
+
candidate: { type: "boolean" }
|
|
5990
|
+
}
|
|
5991
|
+
},
|
|
5888
5992
|
"datasources move": {
|
|
5889
5993
|
usage: "Usage: remy-admin datasources move [--source <slug>] --to <resource-id|shared> [--chains <n>] [--restart] [--wait] [--timeout <sec>] | --stop",
|
|
5890
5994
|
flags: {
|
|
@@ -5928,6 +6032,7 @@ async function dataSourcesAdd(ctx, a) {
|
|
|
5928
6032
|
const slug = sourceOf(a);
|
|
5929
6033
|
const metadata = parseKeyValuePairs(a.str("metadata"), "metadata");
|
|
5930
6034
|
const entities2 = parseIdList(a.str("entities"));
|
|
6035
|
+
const budgetDollars = a.num("budget");
|
|
5931
6036
|
const results = [];
|
|
5932
6037
|
for (const file of files) {
|
|
5933
6038
|
const abs = path6.isAbsolute(file) ? file : path6.join(WORKSPACE_DIR, file);
|
|
@@ -5945,10 +6050,22 @@ async function dataSourcesAdd(ctx, a) {
|
|
|
5945
6050
|
content: bytes,
|
|
5946
6051
|
...metadata ? { metadata } : {},
|
|
5947
6052
|
...entities2 ? { entities: entities2 } : {},
|
|
6053
|
+
...budgetDollars !== void 0 ? { budgetDollars } : {},
|
|
5948
6054
|
onProgress: progress
|
|
5949
6055
|
})
|
|
5950
6056
|
);
|
|
5951
6057
|
}
|
|
6058
|
+
const jobs = results.flatMap(
|
|
6059
|
+
(r) => r.job ? [
|
|
6060
|
+
{
|
|
6061
|
+
file: r.filename,
|
|
6062
|
+
documents: r.documentCount,
|
|
6063
|
+
job: r.job.id,
|
|
6064
|
+
state: r.job.state,
|
|
6065
|
+
follow: `remy-admin datasources jobs status ${r.job.id}`
|
|
6066
|
+
}
|
|
6067
|
+
] : []
|
|
6068
|
+
);
|
|
5952
6069
|
if (a.bool("wait")) {
|
|
5953
6070
|
const timeoutSec = a.num("timeout");
|
|
5954
6071
|
const timeoutMs = timeoutSec ? timeoutSec * 1e3 : DEFAULT_WAIT_TIMEOUT_MS;
|
|
@@ -5964,7 +6081,8 @@ async function dataSourcesAdd(ctx, a) {
|
|
|
5964
6081
|
dataSource: slug,
|
|
5965
6082
|
status: result.status,
|
|
5966
6083
|
...result.error ? { error: result.error } : {},
|
|
5967
|
-
documents: result.documents
|
|
6084
|
+
documents: result.documents,
|
|
6085
|
+
...jobs.length > 0 ? { jobs } : {}
|
|
5968
6086
|
});
|
|
5969
6087
|
if (result.status === "timeout") {
|
|
5970
6088
|
throw new CliError(result.error ?? "Timed out.", EXIT.timeout);
|
|
@@ -5974,7 +6092,11 @@ async function dataSourcesAdd(ctx, a) {
|
|
|
5974
6092
|
}
|
|
5975
6093
|
return;
|
|
5976
6094
|
}
|
|
5977
|
-
out({
|
|
6095
|
+
out({
|
|
6096
|
+
dataSource: slug,
|
|
6097
|
+
documents: results.map(({ job, ...r }) => r),
|
|
6098
|
+
...jobs.length > 0 ? { jobs } : {}
|
|
6099
|
+
});
|
|
5978
6100
|
}
|
|
5979
6101
|
async function dataSourcesList(ctx) {
|
|
5980
6102
|
out(await list8(ctx));
|
|
@@ -6098,6 +6220,22 @@ async function dataSourcesEntities(ctx, a) {
|
|
|
6098
6220
|
})
|
|
6099
6221
|
);
|
|
6100
6222
|
}
|
|
6223
|
+
async function dataSourcesPassages(ctx, a) {
|
|
6224
|
+
const filter = filterFromFlags(a);
|
|
6225
|
+
const limit = a.num("limit");
|
|
6226
|
+
const cursor = a.str("cursor");
|
|
6227
|
+
const result = await passages(ctx, {
|
|
6228
|
+
slug: sourceOf(a),
|
|
6229
|
+
...filter ? { filter } : {},
|
|
6230
|
+
...cursor ? { cursor } : {},
|
|
6231
|
+
...limit !== void 0 ? { limit } : {},
|
|
6232
|
+
...a.bool("candidate") ? { candidate: true } : {}
|
|
6233
|
+
});
|
|
6234
|
+
out({
|
|
6235
|
+
...result,
|
|
6236
|
+
...result.nextCursor ? { note: `More: pass --cursor ${result.nextCursor} for the next page.` } : {}
|
|
6237
|
+
});
|
|
6238
|
+
}
|
|
6101
6239
|
function parseIdList(raw) {
|
|
6102
6240
|
if (raw === void 0) {
|
|
6103
6241
|
return void 0;
|
|
@@ -6362,6 +6500,7 @@ var dataSourcesHandlers = {
|
|
|
6362
6500
|
"datasources config": dataSourcesConfig,
|
|
6363
6501
|
"datasources count": dataSourcesCount,
|
|
6364
6502
|
"datasources entities": dataSourcesEntities,
|
|
6503
|
+
"datasources passages": dataSourcesPassages,
|
|
6365
6504
|
"datasources move": dataSourcesMove,
|
|
6366
6505
|
"datasources revectorize": dataSourcesRevectorize,
|
|
6367
6506
|
"datasources promote": dataSourcesPromote,
|
|
@@ -6379,6 +6518,11 @@ Subcommands:
|
|
|
6379
6518
|
status Show a source's counts and its failed documents (--all walks every document)
|
|
6380
6519
|
rm Remove a document, or every document matching a filter
|
|
6381
6520
|
search Query a corpus \u2014 useful to sanity-check one you just built
|
|
6521
|
+
count How many passages match a filter (words, a phrase, entities, metadata)
|
|
6522
|
+
passages Every passage matching a filter, unranked, a page at a time
|
|
6523
|
+
entities Which entities the matching passages are about, most first
|
|
6524
|
+
dictionary push|status: send a source its dictionary of names, or show the current one
|
|
6525
|
+
link What the source's dictionary finds in a piece of text
|
|
6382
6526
|
create Create an empty source, optionally on dedicated capacity
|
|
6383
6527
|
config Show or change how a corpus is processed and searched
|
|
6384
6528
|
move Move a corpus between shared and dedicated capacity, data intact
|
|
@@ -6391,6 +6535,8 @@ Subcommands:
|
|
|
6391
6535
|
map test Run a source's mapper over real objects and show the outcomes; nothing ingested
|
|
6392
6536
|
map deploy Make a build's compiled mapper the source's active one (a branch build will do)
|
|
6393
6537
|
remap Re-apply the active mapper to every raw copy the source holds
|
|
6538
|
+
reader test|status|retry: run the dev session's reader, see its deliveries, resend failed ones
|
|
6539
|
+
reread Read a source's documents again with its live reader, priced first
|
|
6394
6540
|
hydrate Reload an evicted index ahead of the first search
|
|
6395
6541
|
reindex Recreate a dedicated source's collection with the current shape, refilled from stored vectors
|
|
6396
6542
|
sample Draw a sample of a source into a new one with the same config
|
|
@@ -6401,13 +6547,14 @@ Subcommands:
|
|
|
6401
6547
|
delete Delete a whole data source \u2014 documents, vectors and versions
|
|
6402
6548
|
|
|
6403
6549
|
Usage:
|
|
6404
|
-
remy-admin datasources add [--source <slug>] [--metadata <k=v,...>] [--entities <id,...>] [--wait] [--timeout <sec>] <file...>
|
|
6550
|
+
remy-admin datasources add [--source <slug>] [--metadata <k=v,...>] [--entities <id,...>] [--budget <dollars>] [--wait] [--timeout <sec>] <file...>
|
|
6405
6551
|
remy-admin datasources list
|
|
6406
6552
|
remy-admin datasources status [--source <slug>] [--status error] [--all]
|
|
6407
6553
|
remy-admin datasources rm [--source <slug>] (--document <id> | --filter <k=v,...|json>)
|
|
6408
6554
|
remy-admin datasources search [--source <slug>] [search options] <query>
|
|
6409
6555
|
remy-admin datasources count [--source <slug>] [--filter <k=v,...|json>] [--entities <id,...>] [--contains <words>] [--phrase <text>] [--candidate]
|
|
6410
6556
|
remy-admin datasources entities [--source <slug>] [--filter <k=v,...|json>] [--entities <id,...>] [--limit <n>] [--candidate]
|
|
6557
|
+
remy-admin datasources passages [--source <slug>] [--filter <k=v,...|json>] [--entities <id,...>] [--contains <words>] [--phrase <text>] [--cursor <c>] [--limit <n>] [--candidate]
|
|
6411
6558
|
remy-admin datasources create --source <slug> [--name <name>] [--placement <resource-id|shared>] [rebuild settings...]
|
|
6412
6559
|
remy-admin datasources config [--source <slug>] [--placement <resource-id|shared>] [settings...]
|
|
6413
6560
|
remy-admin datasources move [--source <slug>] --to <resource-id|shared> [--chains <n>] [--restart] [--wait] [--timeout <sec>]
|
|
@@ -6541,6 +6688,10 @@ Notes:
|
|
|
6541
6688
|
--metadata tags documents for search-time filtering (scalars, \u226416 keys).
|
|
6542
6689
|
--entities names what a document is about, as your own ids (\u2264256, no spaces
|
|
6543
6690
|
or commas); an empty --entities clears them. Also free on a re-add.
|
|
6691
|
+
On a mapped source, a file that maps to more than a thousand documents adds
|
|
6692
|
+
the first thousand and starts a job for the rest, listed under \`jobs\` in
|
|
6693
|
+
the output; --budget caps that job. --wait waits for the first thousand;
|
|
6694
|
+
follow the job with \`jobs status <id> --wait\`.
|
|
6544
6695
|
rm --filter removes every matching document in pages of a thousand: k=v
|
|
6545
6696
|
pairs match metadata; a JSON object takes the full selector \u2014 metadata,
|
|
6546
6697
|
filename, documentIds, externalIdPrefix (the key a job or connector
|
|
@@ -9264,32 +9415,60 @@ function resolveRoute(argv) {
|
|
|
9264
9415
|
if (sub && KEYS.has(two)) {
|
|
9265
9416
|
return { key: two, argv: argv.slice(2) };
|
|
9266
9417
|
}
|
|
9267
|
-
if (group === "
|
|
9268
|
-
return {
|
|
9269
|
-
error: `Unknown subcommand: domains custom ${action ?? ""}. Run 'remy-admin domains --help'`
|
|
9270
|
-
};
|
|
9418
|
+
if (group === "db" && sub) {
|
|
9419
|
+
return { key: "db query", argv: argv.slice(1) };
|
|
9271
9420
|
}
|
|
9272
|
-
|
|
9273
|
-
|
|
9274
|
-
|
|
9275
|
-
|
|
9421
|
+
return { error: unknownSubcommand(group, sub, action) };
|
|
9422
|
+
}
|
|
9423
|
+
function keysUnder(words) {
|
|
9424
|
+
const prefix = `${words.join(" ")} `;
|
|
9425
|
+
return [...KEYS].filter((key) => key.startsWith(prefix)).sort();
|
|
9426
|
+
}
|
|
9427
|
+
function unknownSubcommand(group, sub, action) {
|
|
9428
|
+
const asked = [group, sub, action].filter(Boolean).join(" ");
|
|
9429
|
+
const nested = sub ? keysUnder([group, sub]) : [];
|
|
9430
|
+
if (nested.length > 0) {
|
|
9431
|
+
const actions = nested.map((key) => key.split(" ")[2]);
|
|
9432
|
+
return `Unknown subcommand: ${asked}. '${group} ${sub}' takes: ${actions.join(", ")}. Run 'remy-admin ${group} ${sub} --help' for their usage.`;
|
|
9276
9433
|
}
|
|
9277
|
-
|
|
9278
|
-
|
|
9279
|
-
|
|
9280
|
-
|
|
9434
|
+
const subs = [...new Set(keysUnder([group]).map((key) => key.split(" ")[1]))];
|
|
9435
|
+
return `Unknown subcommand: ${asked}. '${group}' takes: ${subs.join(", ")}. Run 'remy-admin ${group} --help'.`;
|
|
9436
|
+
}
|
|
9437
|
+
function leadingWords(argv) {
|
|
9438
|
+
const words = [];
|
|
9439
|
+
for (const token of argv) {
|
|
9440
|
+
if (token.startsWith("-")) {
|
|
9441
|
+
break;
|
|
9442
|
+
}
|
|
9443
|
+
words.push(token);
|
|
9281
9444
|
}
|
|
9282
|
-
|
|
9283
|
-
|
|
9284
|
-
|
|
9285
|
-
|
|
9445
|
+
return words;
|
|
9446
|
+
}
|
|
9447
|
+
function commandHelp(argv) {
|
|
9448
|
+
const words = leadingWords(argv);
|
|
9449
|
+
const group = words[0];
|
|
9450
|
+
const guide = `Run 'remy-admin ${group} --help' for the ${group} guide.`;
|
|
9451
|
+
for (let n = Math.min(words.length, 3); n >= 2; n--) {
|
|
9452
|
+
const key = words.slice(0, n).join(" ");
|
|
9453
|
+
if (KEYS.has(key)) {
|
|
9454
|
+
return `${SPECS[key].usage}
|
|
9455
|
+
|
|
9456
|
+
${guide}`;
|
|
9457
|
+
}
|
|
9286
9458
|
}
|
|
9287
|
-
if (
|
|
9288
|
-
|
|
9459
|
+
if (words.length >= 2) {
|
|
9460
|
+
const under = keysUnder(words.slice(0, 2));
|
|
9461
|
+
if (under.length > 0) {
|
|
9462
|
+
const usages = under.map(
|
|
9463
|
+
(key) => ` ${SPECS[key].usage.replace(/^Usage:\s*/, "")}`
|
|
9464
|
+
);
|
|
9465
|
+
return `Usage:
|
|
9466
|
+
${usages.join("\n")}
|
|
9467
|
+
|
|
9468
|
+
${guide}`;
|
|
9469
|
+
}
|
|
9289
9470
|
}
|
|
9290
|
-
return
|
|
9291
|
-
error: `Unknown subcommand: ${group} ${sub ?? ""}. Run 'remy-admin ${group} --help'`
|
|
9292
|
-
};
|
|
9471
|
+
return void 0;
|
|
9293
9472
|
}
|
|
9294
9473
|
function resolveHelp(argv) {
|
|
9295
9474
|
const group = argv[0];
|
|
@@ -9304,7 +9483,10 @@ function resolveHelp(argv) {
|
|
|
9304
9483
|
return groupHelp;
|
|
9305
9484
|
}
|
|
9306
9485
|
const scan = group === "db" ? argv.slice(1, argv[1] === "query" ? 3 : 2) : argv.slice(1);
|
|
9307
|
-
|
|
9486
|
+
if (!scan.some((t) => t === "--help" || t === "-h")) {
|
|
9487
|
+
return void 0;
|
|
9488
|
+
}
|
|
9489
|
+
return commandHelp(argv) ?? groupHelp;
|
|
9308
9490
|
}
|
|
9309
9491
|
|
|
9310
9492
|
// src/prod.ts
|