@madewithremy/admin 0.1.29 → 0.1.31
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/dist/index.d.ts +549 -46
- package/dist/index.js +164 -53
- package/dist/index.js.map +1 -1
- package/dist/prod.js +671 -95
- package/package.json +2 -2
package/dist/prod.js
CHANGED
|
@@ -36,10 +36,10 @@ function fatal(message) {
|
|
|
36
36
|
throw new CliError(message);
|
|
37
37
|
}
|
|
38
38
|
var AdminApiError = class extends Error {
|
|
39
|
-
constructor(method,
|
|
40
|
-
super(`API ${method} ${
|
|
39
|
+
constructor(method, path8, status2, body) {
|
|
40
|
+
super(`API ${method} ${path8} returned ${status2}: ${JSON.stringify(body)}`);
|
|
41
41
|
this.method = method;
|
|
42
|
-
this.path =
|
|
42
|
+
this.path = path8;
|
|
43
43
|
this.status = status2;
|
|
44
44
|
this.body = body;
|
|
45
45
|
this.name = "AdminApiError";
|
|
@@ -1036,6 +1036,13 @@ function summarizeRelease(release) {
|
|
|
1036
1036
|
publishedAt: release.publishedAt ?? null,
|
|
1037
1037
|
...release.previewUrl ? { previewUrl: release.previewUrl } : {}
|
|
1038
1038
|
};
|
|
1039
|
+
const readers = (release.dataSources ?? []).filter((d) => d.reader);
|
|
1040
|
+
if (readers.length > 0 && release.status === "live") {
|
|
1041
|
+
summary2.readers = readers.map((d) => ({
|
|
1042
|
+
slug: d.slug,
|
|
1043
|
+
unread: d.readerUnread ?? 0
|
|
1044
|
+
}));
|
|
1045
|
+
}
|
|
1039
1046
|
if (release.status !== "failed") {
|
|
1040
1047
|
return summary2;
|
|
1041
1048
|
}
|
|
@@ -3092,8 +3099,8 @@ Notes:
|
|
|
3092
3099
|
- Public image URLs accept transform params, e.g. ?w=400&fit=cover.`;
|
|
3093
3100
|
|
|
3094
3101
|
// src/commands/dataSources.ts
|
|
3095
|
-
import
|
|
3096
|
-
import
|
|
3102
|
+
import fs6 from "fs";
|
|
3103
|
+
import path6 from "path";
|
|
3097
3104
|
|
|
3098
3105
|
// src/ops/dataSources.ts
|
|
3099
3106
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -3111,7 +3118,7 @@ var summarize = (d) => ({
|
|
|
3111
3118
|
...d.errorMessage ? { error: d.errorMessage } : {}
|
|
3112
3119
|
});
|
|
3113
3120
|
async function addDocument(ctx, params) {
|
|
3114
|
-
const { slug, filename, content, metadata, onProgress } = params;
|
|
3121
|
+
const { slug, filename, content, metadata, entities: entities2, onProgress } = params;
|
|
3115
3122
|
const contentHash = createHash2("sha256").update(content).digest("hex");
|
|
3116
3123
|
const token = await call(
|
|
3117
3124
|
ctx,
|
|
@@ -3121,7 +3128,8 @@ async function addDocument(ctx, params) {
|
|
|
3121
3128
|
slug,
|
|
3122
3129
|
filename,
|
|
3123
3130
|
contentHash,
|
|
3124
|
-
...metadata ? { metadata } : {}
|
|
3131
|
+
...metadata ? { metadata } : {},
|
|
3132
|
+
...entities2 ? { entities: entities2 } : {}
|
|
3125
3133
|
}
|
|
3126
3134
|
);
|
|
3127
3135
|
if (token.alreadyCurrent) {
|
|
@@ -3147,7 +3155,8 @@ async function addDocument(ctx, params) {
|
|
|
3147
3155
|
contentHash,
|
|
3148
3156
|
contentType: token.contentType,
|
|
3149
3157
|
size: content.length,
|
|
3150
|
-
...metadata ? { metadata } : {}
|
|
3158
|
+
...metadata ? { metadata } : {},
|
|
3159
|
+
...entities2 ? { entities: entities2 } : {}
|
|
3151
3160
|
}
|
|
3152
3161
|
);
|
|
3153
3162
|
return {
|
|
@@ -3324,6 +3333,20 @@ function count(ctx, params) {
|
|
|
3324
3333
|
...candidate ? { candidate: true } : {}
|
|
3325
3334
|
});
|
|
3326
3335
|
}
|
|
3336
|
+
function entities(ctx, params) {
|
|
3337
|
+
const { slug, filter, limit, candidate } = params;
|
|
3338
|
+
return call(
|
|
3339
|
+
ctx,
|
|
3340
|
+
"POST",
|
|
3341
|
+
`${base(ctx.appId)}/entities`,
|
|
3342
|
+
{
|
|
3343
|
+
slug,
|
|
3344
|
+
...filter ? { filter } : {},
|
|
3345
|
+
...limit !== void 0 ? { limit } : {},
|
|
3346
|
+
...candidate ? { candidate: true } : {}
|
|
3347
|
+
}
|
|
3348
|
+
);
|
|
3349
|
+
}
|
|
3327
3350
|
function configGet(ctx, slug) {
|
|
3328
3351
|
return call(
|
|
3329
3352
|
ctx,
|
|
@@ -3485,6 +3508,67 @@ function deleteSource(ctx, slug) {
|
|
|
3485
3508
|
{ slug }
|
|
3486
3509
|
);
|
|
3487
3510
|
}
|
|
3511
|
+
var DICTIONARY_PAGE_ENTRIES = 1e4;
|
|
3512
|
+
var DICTIONARY_PAGE_BYTES = 4e6;
|
|
3513
|
+
async function pushDictionary(ctx, params) {
|
|
3514
|
+
const { slug, entries } = params;
|
|
3515
|
+
const stage = await call(
|
|
3516
|
+
ctx,
|
|
3517
|
+
"POST",
|
|
3518
|
+
`${base(ctx.appId)}/dictionary/stage`,
|
|
3519
|
+
{
|
|
3520
|
+
slug,
|
|
3521
|
+
...params.linkerVersion !== void 0 ? { linkerVersion: params.linkerVersion } : {}
|
|
3522
|
+
}
|
|
3523
|
+
);
|
|
3524
|
+
const perPage = Math.min(
|
|
3525
|
+
DICTIONARY_PAGE_ENTRIES,
|
|
3526
|
+
stage.pageMaxEntries || DICTIONARY_PAGE_ENTRIES
|
|
3527
|
+
);
|
|
3528
|
+
let pages2 = 0;
|
|
3529
|
+
let start2 = 0;
|
|
3530
|
+
while (start2 < entries.length) {
|
|
3531
|
+
let end = start2;
|
|
3532
|
+
let bytes = 0;
|
|
3533
|
+
while (end < entries.length && end - start2 < perPage) {
|
|
3534
|
+
const size = JSON.stringify(entries[end]).length;
|
|
3535
|
+
if (end > start2 && bytes + size > DICTIONARY_PAGE_BYTES) {
|
|
3536
|
+
break;
|
|
3537
|
+
}
|
|
3538
|
+
bytes += size;
|
|
3539
|
+
end += 1;
|
|
3540
|
+
}
|
|
3541
|
+
await call(ctx, "POST", `${base(ctx.appId)}/dictionary/page`, {
|
|
3542
|
+
slug,
|
|
3543
|
+
stageId: stage.stageId,
|
|
3544
|
+
page: pages2,
|
|
3545
|
+
entries: entries.slice(start2, end)
|
|
3546
|
+
});
|
|
3547
|
+
pages2 += 1;
|
|
3548
|
+
start2 = end;
|
|
3549
|
+
params.onProgress?.(start2, entries.length);
|
|
3550
|
+
}
|
|
3551
|
+
return call(
|
|
3552
|
+
ctx,
|
|
3553
|
+
"POST",
|
|
3554
|
+
`${base(ctx.appId)}/dictionary/commit`,
|
|
3555
|
+
{ slug, stageId: stage.stageId, pages: pages2 }
|
|
3556
|
+
);
|
|
3557
|
+
}
|
|
3558
|
+
function dictionary(ctx, params) {
|
|
3559
|
+
return call(
|
|
3560
|
+
ctx,
|
|
3561
|
+
"POST",
|
|
3562
|
+
`${base(ctx.appId)}/dictionary`,
|
|
3563
|
+
{ slug: params.slug }
|
|
3564
|
+
);
|
|
3565
|
+
}
|
|
3566
|
+
function link(ctx, params) {
|
|
3567
|
+
return call(ctx, "POST", `${base(ctx.appId)}/link`, {
|
|
3568
|
+
slug: params.slug,
|
|
3569
|
+
text: params.text
|
|
3570
|
+
});
|
|
3571
|
+
}
|
|
3488
3572
|
|
|
3489
3573
|
// src/ops/dataSourceJobs.ts
|
|
3490
3574
|
var DEFAULT_WAIT_TIMEOUT_MS2 = 60 * 60 * 1e3;
|
|
@@ -3643,6 +3727,39 @@ function describeProgress(job, start2) {
|
|
|
3643
3727
|
// src/commands/_shared/dataSources.ts
|
|
3644
3728
|
var DEFAULT_SOURCE = "default";
|
|
3645
3729
|
var sourceOf = (a) => a.str("source") || DEFAULT_SOURCE;
|
|
3730
|
+
function parseKeyValuePairs(raw, flag) {
|
|
3731
|
+
if (raw === void 0) {
|
|
3732
|
+
return void 0;
|
|
3733
|
+
}
|
|
3734
|
+
const pairs2 = {};
|
|
3735
|
+
for (const part of raw.split(",")) {
|
|
3736
|
+
const trimmed = part.trim();
|
|
3737
|
+
if (!trimmed) {
|
|
3738
|
+
continue;
|
|
3739
|
+
}
|
|
3740
|
+
const eq = trimmed.indexOf("=");
|
|
3741
|
+
if (eq <= 0) {
|
|
3742
|
+
fatal(`--${flag} entries must be key=value (got "${trimmed}").`);
|
|
3743
|
+
}
|
|
3744
|
+
const key = trimmed.slice(0, eq).trim();
|
|
3745
|
+
const value = trimmed.slice(eq + 1).trim();
|
|
3746
|
+
pairs2[key] = value === "true" ? true : value === "false" ? false : value !== "" && !Number.isNaN(Number(value)) ? Number(value) : value;
|
|
3747
|
+
}
|
|
3748
|
+
if (Object.keys(pairs2).length === 0) {
|
|
3749
|
+
fatal(`--${flag} needs at least one key=value pair.`);
|
|
3750
|
+
}
|
|
3751
|
+
return pairs2;
|
|
3752
|
+
}
|
|
3753
|
+
function documentSelectorOf(raw) {
|
|
3754
|
+
if (raw.trimStart().startsWith("{")) {
|
|
3755
|
+
try {
|
|
3756
|
+
return JSON.parse(raw);
|
|
3757
|
+
} catch (err) {
|
|
3758
|
+
fatal(`--filter is not valid JSON: ${err.message}`);
|
|
3759
|
+
}
|
|
3760
|
+
}
|
|
3761
|
+
return { metadata: parseKeyValuePairs(raw, "filter") };
|
|
3762
|
+
}
|
|
3646
3763
|
var timeoutOf = (a) => {
|
|
3647
3764
|
const seconds = a.str("timeout");
|
|
3648
3765
|
return seconds ? { timeoutMs: Number(seconds) * 1e3 } : {};
|
|
@@ -4658,9 +4775,116 @@ Retrieval evals:
|
|
|
4658
4775
|
with --candidate, compare, promote or drop.
|
|
4659
4776
|
`;
|
|
4660
4777
|
|
|
4661
|
-
// src/commands/
|
|
4778
|
+
// src/commands/dataSourceDictionary.ts
|
|
4662
4779
|
import fs4 from "fs";
|
|
4663
4780
|
import path4 from "path";
|
|
4781
|
+
var dataSourceDictionarySpecs = {
|
|
4782
|
+
"datasources dictionary push": {
|
|
4783
|
+
usage: "Usage: remy-admin datasources dictionary push [--source <slug>] [--linker-version <n>] <file.jsonl>",
|
|
4784
|
+
positionals: [{ name: "file", required: true }],
|
|
4785
|
+
flags: {
|
|
4786
|
+
source: { type: "string" },
|
|
4787
|
+
"linker-version": { type: "number", min: 1 }
|
|
4788
|
+
}
|
|
4789
|
+
},
|
|
4790
|
+
"datasources dictionary status": {
|
|
4791
|
+
usage: "Usage: remy-admin datasources dictionary status [--source <slug>]",
|
|
4792
|
+
flags: {
|
|
4793
|
+
source: { type: "string" }
|
|
4794
|
+
}
|
|
4795
|
+
},
|
|
4796
|
+
"datasources link": {
|
|
4797
|
+
usage: "Usage: remy-admin datasources link [--source <slug>] <text>",
|
|
4798
|
+
positionals: [{ name: "text", required: true }],
|
|
4799
|
+
flags: {
|
|
4800
|
+
source: { type: "string" }
|
|
4801
|
+
}
|
|
4802
|
+
}
|
|
4803
|
+
};
|
|
4804
|
+
function readEntries(file) {
|
|
4805
|
+
const abs = path4.isAbsolute(file) ? file : path4.join(WORKSPACE_DIR, file);
|
|
4806
|
+
let content;
|
|
4807
|
+
try {
|
|
4808
|
+
content = fs4.readFileSync(abs, "utf8");
|
|
4809
|
+
} catch (err) {
|
|
4810
|
+
fatal(`Could not read "${file}": ${err.message}`);
|
|
4811
|
+
}
|
|
4812
|
+
const entries = [];
|
|
4813
|
+
content.split("\n").forEach((line, i) => {
|
|
4814
|
+
const trimmed = line.trim();
|
|
4815
|
+
if (!trimmed) {
|
|
4816
|
+
return;
|
|
4817
|
+
}
|
|
4818
|
+
let parsed;
|
|
4819
|
+
try {
|
|
4820
|
+
parsed = JSON.parse(trimmed);
|
|
4821
|
+
} catch {
|
|
4822
|
+
fatal(`${file}:${i + 1} is not valid JSON.`);
|
|
4823
|
+
}
|
|
4824
|
+
if (typeof parsed?.id !== "string" || !Array.isArray(parsed?.names) || !parsed.names.every((name) => typeof name === "string")) {
|
|
4825
|
+
fatal(`${file}:${i + 1} needs { "id": "...", "names": ["...", ...] }.`);
|
|
4826
|
+
}
|
|
4827
|
+
entries.push({ id: parsed.id, names: parsed.names });
|
|
4828
|
+
});
|
|
4829
|
+
if (entries.length === 0) {
|
|
4830
|
+
fatal(`"${file}" has no entries.`);
|
|
4831
|
+
}
|
|
4832
|
+
return entries;
|
|
4833
|
+
}
|
|
4834
|
+
async function dictionaryPush(ctx, a) {
|
|
4835
|
+
const entries = readEntries(a.req("file"));
|
|
4836
|
+
const linkerVersion = a.num("linker-version");
|
|
4837
|
+
out(
|
|
4838
|
+
await pushDictionary(ctx, {
|
|
4839
|
+
slug: sourceOf(a),
|
|
4840
|
+
entries,
|
|
4841
|
+
...linkerVersion !== void 0 ? { linkerVersion } : {},
|
|
4842
|
+
onProgress: (sent, total) => progress(`pushing ${sent.toLocaleString()}/${total.toLocaleString()}\u2026`)
|
|
4843
|
+
})
|
|
4844
|
+
);
|
|
4845
|
+
}
|
|
4846
|
+
async function dictionaryStatus(ctx, a) {
|
|
4847
|
+
out(await dictionary(ctx, { slug: sourceOf(a) }));
|
|
4848
|
+
}
|
|
4849
|
+
async function link2(ctx, a) {
|
|
4850
|
+
out(await link(ctx, { slug: sourceOf(a), text: a.req("text") }));
|
|
4851
|
+
}
|
|
4852
|
+
var dataSourceDictionaryHandlers = {
|
|
4853
|
+
"datasources dictionary push": dictionaryPush,
|
|
4854
|
+
"datasources dictionary status": dictionaryStatus,
|
|
4855
|
+
"datasources link": link2
|
|
4856
|
+
};
|
|
4857
|
+
var dataSourceDictionaryHelp = `
|
|
4858
|
+
Dictionary:
|
|
4859
|
+
remy-admin datasources dictionary push [--source <slug>] [--linker-version <n>] <file.jsonl>
|
|
4860
|
+
remy-admin datasources dictionary status [--source <slug>]
|
|
4861
|
+
remy-admin datasources link [--source <slug>] <text>
|
|
4862
|
+
|
|
4863
|
+
A dictionary is your own entity ids and the names each goes by, a
|
|
4864
|
+
projection of your tables: one JSONL line per entry,
|
|
4865
|
+
{"id": "P-101A", "names": ["P-101A", "Main Feed Pump"]}. Push it whole; it
|
|
4866
|
+
replaces the source's dictionary. From then on every passage carries the
|
|
4867
|
+
ids whose names its text mentions, beside the ones its document asserts,
|
|
4868
|
+
so --entities on search and count, and \`datasources entities\`, find a tag
|
|
4869
|
+
wherever it's written. Passages indexed before are re-tagged in the
|
|
4870
|
+
background (a relink; \`dictionary status\` shows it), with nothing
|
|
4871
|
+
re-embedded. An unchanged dictionary commits nothing.
|
|
4872
|
+
|
|
4873
|
+
Matching ignores case and a tag's separators (P-101A, P101A, p 101a), takes
|
|
4874
|
+
whole words only (P-101AB is not P-101A), and prefers the longest name; a
|
|
4875
|
+
name two ids claim tags both. A name needs three letters or digits (two in
|
|
4876
|
+
Chinese, Japanese or Korean). The push reports ambiguous names, the most
|
|
4877
|
+
claimed, and names that can't match their own text as written
|
|
4878
|
+
(\`unmatchable\`). Up to 250,000 entries, 16 names each, a million names.
|
|
4879
|
+
|
|
4880
|
+
\`link\` shows what the current dictionary finds in any text: check one
|
|
4881
|
+
there before relying on it. --linker-version moves a dictionary to a newer
|
|
4882
|
+
matching rule; without it a push keeps the one its dictionary has.
|
|
4883
|
+
`;
|
|
4884
|
+
|
|
4885
|
+
// src/commands/dataSourceJobs.ts
|
|
4886
|
+
import fs5 from "fs";
|
|
4887
|
+
import path5 from "path";
|
|
4664
4888
|
var dataSourceJobsSpecs = {
|
|
4665
4889
|
"datasources jobs start": {
|
|
4666
4890
|
usage: "Usage: remy-admin datasources jobs start [--source <slug>] (--store <name> [--access <private|public>] [--prefix <p>] | --manifest <file.jsonl>) [--limit <n>] [--budget <dollars>] [--concurrency <n>] [--priority] [--approve] [--wait] [--timeout <sec>]",
|
|
@@ -4738,10 +4962,10 @@ async function jobsStart(ctx, a) {
|
|
|
4738
4962
|
}
|
|
4739
4963
|
let source;
|
|
4740
4964
|
if (manifest) {
|
|
4741
|
-
const abs =
|
|
4965
|
+
const abs = path5.isAbsolute(manifest) ? manifest : path5.join(WORKSPACE_DIR, manifest);
|
|
4742
4966
|
let content;
|
|
4743
4967
|
try {
|
|
4744
|
-
content =
|
|
4968
|
+
content = fs5.readFileSync(abs);
|
|
4745
4969
|
} catch (err) {
|
|
4746
4970
|
fatal(`Could not read manifest "${manifest}": ${err.message}`);
|
|
4747
4971
|
}
|
|
@@ -4867,12 +5091,13 @@ Bulk ingestion (jobs):
|
|
|
4867
5091
|
A job loads a whole corpus at once. It reads either every object under a
|
|
4868
5092
|
prefix of one of the app's file stores (\`files put\` fills one; an app can
|
|
4869
5093
|
write one at runtime) or a manifest you upload: JSONL, one line per document,
|
|
4870
|
-
{"url": "https://\u2026", "filename": "x.pdf", "externalId": "\u2026", "metadata": {\u2026}
|
|
4871
|
-
|
|
5094
|
+
{"url": "https://\u2026", "filename": "x.pdf", "externalId": "\u2026", "metadata": {\u2026},
|
|
5095
|
+
"entities": ["\u2026"]}. Everything but the URL is optional; it must be public.
|
|
4872
5096
|
|
|
4873
|
-
Nothing
|
|
4874
|
-
sample of about a hundred documents, and writes a plan:
|
|
4875
|
-
cost per stage (embedding, extraction, contextual
|
|
5097
|
+
Nothing past the sample runs until you say so. The platform counts the
|
|
5098
|
+
source, reads a sample of about a hundred documents, and writes a plan:
|
|
5099
|
+
documents, chunks, cost per stage (embedding, extraction, contextual, and
|
|
5100
|
+
the mapper's own model calls, priced from the sample's) at today's rates, storage,
|
|
4876
5101
|
whether it fits where the source lives, and a duration. \`jobs status\` shows
|
|
4877
5102
|
it; \`jobs approve\` starts the run. Two gates: the corpus has to fit the
|
|
4878
5103
|
source's placement (a shared-pool source over the per-source cap answers
|
|
@@ -4982,6 +5207,7 @@ function quarantine(ctx, params) {
|
|
|
4982
5207
|
"GET",
|
|
4983
5208
|
`${base5(ctx.appId)}/jobs/${params.id}/quarantine${qs({
|
|
4984
5209
|
...params.kind ? { kind: params.kind } : {},
|
|
5210
|
+
...params.stage ? { stage: params.stage } : {},
|
|
4985
5211
|
...params.reason ? { reason: params.reason } : {},
|
|
4986
5212
|
...params.cursor ? { cursor: params.cursor } : {},
|
|
4987
5213
|
...params.limit !== void 0 ? { limit: params.limit } : {}
|
|
@@ -5050,10 +5276,11 @@ var dataSourceMappersSpecs = {
|
|
|
5050
5276
|
}
|
|
5051
5277
|
},
|
|
5052
5278
|
"datasources jobs quarantine": {
|
|
5053
|
-
usage: "Usage: remy-admin datasources jobs quarantine <id> [--kind skip|error] [--reason <text>] [--cursor <id>] [--limit <n>]",
|
|
5279
|
+
usage: "Usage: remy-admin datasources jobs quarantine <id> [--kind skip|error] [--stage map|read] [--reason <text>] [--cursor <id>] [--limit <n>]",
|
|
5054
5280
|
positionals: [{ name: "id", required: true }],
|
|
5055
5281
|
flags: {
|
|
5056
5282
|
kind: { type: "string" },
|
|
5283
|
+
stage: { type: "string" },
|
|
5057
5284
|
reason: { type: "string" },
|
|
5058
5285
|
cursor: { type: "string" },
|
|
5059
5286
|
limit: { type: "number", min: 1 }
|
|
@@ -5206,18 +5433,32 @@ async function quarantine2(ctx, a) {
|
|
|
5206
5433
|
const id = a.req("id");
|
|
5207
5434
|
const limit = a.num("limit");
|
|
5208
5435
|
const kind = kindOf(a);
|
|
5436
|
+
const stage = a.str("stage");
|
|
5437
|
+
if (stage !== void 0 && stage !== "map" && stage !== "read") {
|
|
5438
|
+
fatal(`--stage must be "map" or "read" (got "${stage}").`);
|
|
5439
|
+
}
|
|
5209
5440
|
const reason = a.str("reason");
|
|
5210
5441
|
const cursor = a.str("cursor");
|
|
5211
5442
|
const result = await quarantine(ctx, {
|
|
5212
5443
|
id,
|
|
5213
5444
|
...kind ? { kind } : {},
|
|
5445
|
+
...stage ? { stage } : {},
|
|
5214
5446
|
...reason ? { reason } : {},
|
|
5215
5447
|
...cursor ? { cursor } : {},
|
|
5216
5448
|
...limit !== void 0 ? { limit } : {}
|
|
5217
5449
|
});
|
|
5450
|
+
const { skipped, errors, readErrors } = result.counts;
|
|
5451
|
+
const notes = [
|
|
5452
|
+
...skipped + errors > 0 ? [
|
|
5453
|
+
`Mapping: fix the mapper, push, \`datasources map deploy\`, then \`datasources jobs replay ${id}\` to run these through it again.`
|
|
5454
|
+
] : [],
|
|
5455
|
+
...readErrors > 0 ? [
|
|
5456
|
+
`Reading: fix the reader and publish, then \`datasources reader retry --source ${result.dataSource.slug} --job ${id}\` reads these again.`
|
|
5457
|
+
] : []
|
|
5458
|
+
];
|
|
5218
5459
|
out({
|
|
5219
5460
|
...result,
|
|
5220
|
-
note:
|
|
5461
|
+
note: notes.length === 0 ? "Nothing quarantined: the mapper produced documents (or deletions) for every object, and the reader read every document." : notes.join(" ")
|
|
5221
5462
|
});
|
|
5222
5463
|
}
|
|
5223
5464
|
async function replay2(ctx, a) {
|
|
@@ -5258,7 +5499,7 @@ Mapping raw objects into documents (mappers):
|
|
|
5258
5499
|
remy-admin datasources map test [--source <slug>] (--store <name> [--prefix <p>] | --connector) [--keys k1,k2] [--limit <n>] [--dev] [--full]
|
|
5259
5500
|
remy-admin datasources map deploy [--source <slug>] [--release <id>]
|
|
5260
5501
|
remy-admin datasources remap [--source <slug>] [--budget <dollars>] [--limit <n>] [--wait] [--timeout <sec>]
|
|
5261
|
-
remy-admin datasources jobs quarantine <id> [--kind skip|error] [--reason <text>] [--cursor <id>] [--limit <n>]
|
|
5502
|
+
remy-admin datasources jobs quarantine <id> [--kind skip|error] [--stage map|read] [--reason <text>] [--cursor <id>] [--limit <n>]
|
|
5262
5503
|
remy-admin datasources jobs replay <id> [--kind skip|error] [--wait] [--timeout <sec>]
|
|
5263
5504
|
|
|
5264
5505
|
A source takes every object it is given as one document. When the file is
|
|
@@ -5299,6 +5540,228 @@ Mapping raw objects into documents (mappers):
|
|
|
5299
5540
|
pauses with pauseReason 'skips' for a look at the quarantine.
|
|
5300
5541
|
`;
|
|
5301
5542
|
|
|
5543
|
+
// src/ops/dataSourceReaders.ts
|
|
5544
|
+
function base6(appId) {
|
|
5545
|
+
return `/_internal/v2/apps/${appId}/datasources`;
|
|
5546
|
+
}
|
|
5547
|
+
function readerTest(ctx, params) {
|
|
5548
|
+
return call(
|
|
5549
|
+
ctx,
|
|
5550
|
+
"POST",
|
|
5551
|
+
`${base6(ctx.appId)}/reader/test`,
|
|
5552
|
+
{
|
|
5553
|
+
slug: params.slug,
|
|
5554
|
+
...params.documents ? { documents: params.documents } : {},
|
|
5555
|
+
...params.limit !== void 0 ? { limit: params.limit } : {}
|
|
5556
|
+
}
|
|
5557
|
+
);
|
|
5558
|
+
}
|
|
5559
|
+
function readerStatus(ctx, params) {
|
|
5560
|
+
return call(
|
|
5561
|
+
ctx,
|
|
5562
|
+
"POST",
|
|
5563
|
+
`${base6(ctx.appId)}/reader/status`,
|
|
5564
|
+
{ slug: params.slug }
|
|
5565
|
+
);
|
|
5566
|
+
}
|
|
5567
|
+
function readerRetry(ctx, params) {
|
|
5568
|
+
return call(
|
|
5569
|
+
ctx,
|
|
5570
|
+
"POST",
|
|
5571
|
+
`${base6(ctx.appId)}/reader/retry`,
|
|
5572
|
+
{
|
|
5573
|
+
slug: params.slug,
|
|
5574
|
+
...params.jobId ? { jobId: params.jobId } : {}
|
|
5575
|
+
}
|
|
5576
|
+
);
|
|
5577
|
+
}
|
|
5578
|
+
function reread(ctx, params) {
|
|
5579
|
+
return call(
|
|
5580
|
+
ctx,
|
|
5581
|
+
"POST",
|
|
5582
|
+
`${base6(ctx.appId)}/reread`,
|
|
5583
|
+
{
|
|
5584
|
+
slug: params.slug,
|
|
5585
|
+
...params.unread ? { unread: true } : {},
|
|
5586
|
+
...params.filter ? { filter: params.filter } : {},
|
|
5587
|
+
...params.budgetDollars !== void 0 ? { budgetDollars: params.budgetDollars } : {},
|
|
5588
|
+
...params.limit !== void 0 ? { limit: params.limit } : {}
|
|
5589
|
+
}
|
|
5590
|
+
);
|
|
5591
|
+
}
|
|
5592
|
+
|
|
5593
|
+
// src/commands/dataSourceReaders.ts
|
|
5594
|
+
var dataSourceReadersSpecs = {
|
|
5595
|
+
"datasources reader test": {
|
|
5596
|
+
usage: "Usage: remy-admin datasources reader test --dev [--source <slug>] [--documents id1,id2,...] [--limit <n>]",
|
|
5597
|
+
flags: {
|
|
5598
|
+
source: { type: "string" },
|
|
5599
|
+
dev: { type: "boolean" },
|
|
5600
|
+
documents: { type: "string" },
|
|
5601
|
+
limit: { type: "number", min: 1 }
|
|
5602
|
+
}
|
|
5603
|
+
},
|
|
5604
|
+
"datasources reader status": {
|
|
5605
|
+
usage: "Usage: remy-admin datasources reader status [--source <slug>]",
|
|
5606
|
+
flags: {
|
|
5607
|
+
source: { type: "string" }
|
|
5608
|
+
}
|
|
5609
|
+
},
|
|
5610
|
+
"datasources reader retry": {
|
|
5611
|
+
usage: "Usage: remy-admin datasources reader retry [--source <slug>] [--job <id>]",
|
|
5612
|
+
flags: {
|
|
5613
|
+
source: { type: "string" },
|
|
5614
|
+
job: { type: "string" }
|
|
5615
|
+
}
|
|
5616
|
+
},
|
|
5617
|
+
"datasources reread": {
|
|
5618
|
+
usage: "Usage: remy-admin datasources reread [--source <slug>] [--unread] [--filter <k=v,...|json>] [--budget <dollars>] [--limit <n>] [--wait] [--timeout <sec>]",
|
|
5619
|
+
flags: {
|
|
5620
|
+
source: { type: "string" },
|
|
5621
|
+
unread: { type: "boolean" },
|
|
5622
|
+
filter: { type: "string" },
|
|
5623
|
+
budget: { type: "number", min: 0.01 },
|
|
5624
|
+
limit: { type: "number", min: 1 },
|
|
5625
|
+
wait: { type: "boolean" },
|
|
5626
|
+
timeout: { type: "string" }
|
|
5627
|
+
}
|
|
5628
|
+
}
|
|
5629
|
+
};
|
|
5630
|
+
async function readerTest2(ctx, a) {
|
|
5631
|
+
if (!a.bool("dev")) {
|
|
5632
|
+
fatal(
|
|
5633
|
+
"reader test runs the dev session's reader only: pass --dev. The live reader reads through deliveries and `datasources reread`."
|
|
5634
|
+
);
|
|
5635
|
+
}
|
|
5636
|
+
const slug = sourceOf(a);
|
|
5637
|
+
const raw = a.str("documents");
|
|
5638
|
+
const documents2 = raw?.split(",").map((id) => id.trim()).filter(Boolean);
|
|
5639
|
+
if (raw !== void 0 && documents2?.length === 0) {
|
|
5640
|
+
fatal("--documents needs at least one document id.");
|
|
5641
|
+
}
|
|
5642
|
+
const limit = a.num("limit");
|
|
5643
|
+
const result = await readerTest(ctx, {
|
|
5644
|
+
slug,
|
|
5645
|
+
...documents2 ? { documents: documents2 } : {},
|
|
5646
|
+
...limit !== void 0 ? { limit } : {}
|
|
5647
|
+
});
|
|
5648
|
+
out({
|
|
5649
|
+
dataSource: slug,
|
|
5650
|
+
...result,
|
|
5651
|
+
note: "Ran the LOCAL reader through the dev session, writing into the dev session's database. Query its tables to check what it wrote; publish to make it the live reader, then `datasources reread --unread` reads what it has not."
|
|
5652
|
+
});
|
|
5653
|
+
if (result.failed > 0) {
|
|
5654
|
+
throw new CliError(
|
|
5655
|
+
`The reader failed on ${result.failed} of ${result.documents.length} document(s).`,
|
|
5656
|
+
EXIT.buildFailed
|
|
5657
|
+
);
|
|
5658
|
+
}
|
|
5659
|
+
}
|
|
5660
|
+
async function readerStatus2(ctx, a) {
|
|
5661
|
+
const slug = sourceOf(a);
|
|
5662
|
+
const result = await readerStatus(ctx, { slug });
|
|
5663
|
+
const { reader, deliveries, documents: documents2 } = result;
|
|
5664
|
+
out({
|
|
5665
|
+
dataSource: slug,
|
|
5666
|
+
...result,
|
|
5667
|
+
note: !reader ? `The live release declares no reader for "${slug}". Declare one in mindstudio.json's dataSources and publish.` : deliveries.parked > 0 ? `${deliveries.parked} delivery(ies) failed six times and parked. Fix the reader and publish, then \`datasources reader retry\`.` : documents2.unread > 0 ? `${documents2.unread.toLocaleString()} live document(s) not read yet. \`datasources reread --unread\` plans reading them.` : "Every live document has been read."
|
|
5668
|
+
});
|
|
5669
|
+
}
|
|
5670
|
+
async function readerRetry2(ctx, a) {
|
|
5671
|
+
const slug = sourceOf(a);
|
|
5672
|
+
const jobId = a.str("job");
|
|
5673
|
+
const result = await readerRetry(ctx, {
|
|
5674
|
+
slug,
|
|
5675
|
+
...jobId ? { jobId } : {}
|
|
5676
|
+
});
|
|
5677
|
+
out({
|
|
5678
|
+
dataSource: slug,
|
|
5679
|
+
...jobId ? { job: jobId } : {},
|
|
5680
|
+
...result,
|
|
5681
|
+
note: result.retried === 0 ? jobId ? `Job ${jobId}'s reader failed on nothing.` : "Nothing parked." : `Queued ${result.retried.toLocaleString()} delivery(ies) again; \`datasources reader status\` shows them drain.`
|
|
5682
|
+
});
|
|
5683
|
+
}
|
|
5684
|
+
async function reread2(ctx, a) {
|
|
5685
|
+
const slug = sourceOf(a);
|
|
5686
|
+
const raw = a.str("filter");
|
|
5687
|
+
const budget = a.num("budget");
|
|
5688
|
+
const limit = a.num("limit");
|
|
5689
|
+
const { job } = await reread(ctx, {
|
|
5690
|
+
slug,
|
|
5691
|
+
...a.bool("unread") ? { unread: true } : {},
|
|
5692
|
+
...raw !== void 0 ? { filter: documentSelectorOf(raw) } : {},
|
|
5693
|
+
...budget !== void 0 ? { budgetDollars: budget } : {},
|
|
5694
|
+
...limit !== void 0 ? { limit } : {}
|
|
5695
|
+
});
|
|
5696
|
+
if (!a.bool("wait")) {
|
|
5697
|
+
out({
|
|
5698
|
+
dataSource: slug,
|
|
5699
|
+
job,
|
|
5700
|
+
note: `Planning: the reread prices reading from the reader's history, or reads a first slice for real to measure it. \`datasources jobs status ${job.id}\` shows the plan; \`datasources jobs approve ${job.id}\` runs it.`
|
|
5701
|
+
});
|
|
5702
|
+
return;
|
|
5703
|
+
}
|
|
5704
|
+
await waitAndReport(ctx, a, job.id, "plan", {
|
|
5705
|
+
dataSource: slug,
|
|
5706
|
+
action: "reread"
|
|
5707
|
+
});
|
|
5708
|
+
}
|
|
5709
|
+
var dataSourceReadersHandlers = {
|
|
5710
|
+
"datasources reader test": readerTest2,
|
|
5711
|
+
"datasources reader status": readerStatus2,
|
|
5712
|
+
"datasources reader retry": readerRetry2,
|
|
5713
|
+
"datasources reread": reread2
|
|
5714
|
+
};
|
|
5715
|
+
var dataSourceReadersHelp = `
|
|
5716
|
+
Reading documents into the app (readers):
|
|
5717
|
+
remy-admin datasources reader test --dev [--source <slug>] [--documents id1,id2] [--limit <n>]
|
|
5718
|
+
remy-admin datasources reader status [--source <slug>]
|
|
5719
|
+
remy-admin datasources reader retry [--source <slug>] [--job <id>]
|
|
5720
|
+
remy-admin datasources reread [--source <slug>] [--unread] [--filter <k=v|json>] [--budget <dollars>] [--limit <n>] [--wait] [--timeout <sec>]
|
|
5721
|
+
|
|
5722
|
+
A READER is app code the platform runs over every document a source
|
|
5723
|
+
builds, writing what it finds into the app's own tables: the extraction an
|
|
5724
|
+
app would otherwise run from a cron over allDocuments(), with the
|
|
5725
|
+
platform's batching, retries, budgets and pauses. Declare it in
|
|
5726
|
+
mindstudio.json:
|
|
5727
|
+
"dataSources": [{ "slug": "archive", "reader": { "path": "dist/datasources/archive.reader.ts" } }]
|
|
5728
|
+
The file exports defineReader(Archive, { read, removed, cleared? }) from
|
|
5729
|
+
@mindstudio-ai/agent. read(document) gets the document (id, sourceId,
|
|
5730
|
+
filename, metadata, entities) and document.chunks(), its passages as
|
|
5731
|
+
indexed with each one's entities; removed(documentId) is called when a
|
|
5732
|
+
document leaves the source; cleared(sourceId) once when the source is
|
|
5733
|
+
deleted. Throwing fails that document, which is retried. A document can be
|
|
5734
|
+
read more than once, so read() replaces the document's rows as a set,
|
|
5735
|
+
keyed by its id, and removed() deletes them. Options on the declaration:
|
|
5736
|
+
timeoutMs (per document, default 60000, max 300000) and concurrency
|
|
5737
|
+
(frames in flight for the source, default 16, max 64).
|
|
5738
|
+
|
|
5739
|
+
The reader always runs against the LIVE release, its code and its
|
|
5740
|
+
database: nothing reads until the app publishes one. From then on every
|
|
5741
|
+
document whose build lands on the active version is read, every removed
|
|
5742
|
+
document delivered as removed, whether it came through add(), a sync or a
|
|
5743
|
+
job. A job over a reader source reads as its last stage: the job stays
|
|
5744
|
+
running until its documents are read, \`jobs status\` says "reading N of M",
|
|
5745
|
+
a document the reader fails on lands in the job's quarantine (stage read),
|
|
5746
|
+
and a reader failing on far more documents than it did at first pauses the
|
|
5747
|
+
job with pauseReason 'reader'.
|
|
5748
|
+
|
|
5749
|
+
The loop: \`reader test --dev\` runs the LOCAL reader through the dev
|
|
5750
|
+
session over real documents, writing into the dev session's database, and
|
|
5751
|
+
prints each outcome; publish, and \`releases wait\` reports each reader's
|
|
5752
|
+
unread documents; \`reread --unread\` reads them. \`reread\` is a job that
|
|
5753
|
+
plans first: it prices reading from what the live reader has done (after a
|
|
5754
|
+
hundred documents), or reads a first slice for real and measures spend,
|
|
5755
|
+
failures and the live database's growth, then waits for \`jobs approve\`.
|
|
5756
|
+
Without --unread it reads every built document again (a changed reader).
|
|
5757
|
+
\`reader status\` shows the reader, its deliveries (pending, in flight,
|
|
5758
|
+
retrying, parked, recent errors), unread documents, the measured cost per
|
|
5759
|
+
document and the live database's size. Deliveries outside jobs retry after
|
|
5760
|
+
1, 5, 15, 60 and 240 minutes, then park; \`reader retry\` sends parked ones
|
|
5761
|
+
again, and \`reader retry --job <id>\` the documents a job's reader failed
|
|
5762
|
+
on.
|
|
5763
|
+
`;
|
|
5764
|
+
|
|
5302
5765
|
// src/commands/dataSources.ts
|
|
5303
5766
|
var INGEST_FLAGS = {
|
|
5304
5767
|
chunking: { type: "string" },
|
|
@@ -5329,11 +5792,12 @@ var CONFIG_FLAGS = {
|
|
|
5329
5792
|
};
|
|
5330
5793
|
var dataSourcesSpecs = {
|
|
5331
5794
|
"datasources add": {
|
|
5332
|
-
usage: "Usage: remy-admin datasources add [--source <slug>] [--metadata <k=v,...>] [--wait] [--timeout <sec>] <file...>",
|
|
5795
|
+
usage: "Usage: remy-admin datasources add [--source <slug>] [--metadata <k=v,...>] [--entities <id,...>] [--wait] [--timeout <sec>] <file...>",
|
|
5333
5796
|
positionals: [{ name: "file", required: true, variadic: true }],
|
|
5334
5797
|
flags: {
|
|
5335
5798
|
source: { type: "string" },
|
|
5336
5799
|
metadata: { type: "string" },
|
|
5800
|
+
entities: { type: "string" },
|
|
5337
5801
|
wait: { type: "boolean" },
|
|
5338
5802
|
timeout: { type: "string" }
|
|
5339
5803
|
}
|
|
@@ -5362,7 +5826,7 @@ var dataSourcesSpecs = {
|
|
|
5362
5826
|
}
|
|
5363
5827
|
},
|
|
5364
5828
|
"datasources search": {
|
|
5365
|
-
usage: "Usage: remy-admin datasources search [--source <slug>] [--top-k <n>] [--mode <hybrid|semantic|lexical>] [--filter <k=v,...|json>] [--phrase <text>] [--contains <words>] [--max-per-document <n>] [--rerank <true|false>] [--hybrid <true|false>] [--highlight] [--candidate] <query>",
|
|
5829
|
+
usage: "Usage: remy-admin datasources search [--source <slug>] [--top-k <n>] [--mode <hybrid|semantic|lexical>] [--filter <k=v,...|json>] [--entities <id,...>] [--phrase <text>] [--contains <words>] [--max-per-document <n>] [--rerank <true|false>] [--hybrid <true|false>] [--highlight] [--candidate] <query>",
|
|
5366
5830
|
positionals: [{ name: "query", required: true }],
|
|
5367
5831
|
flags: {
|
|
5368
5832
|
source: { type: "string" },
|
|
@@ -5372,6 +5836,7 @@ var dataSourcesSpecs = {
|
|
|
5372
5836
|
hybrid: { type: "string" },
|
|
5373
5837
|
mode: { type: "string" },
|
|
5374
5838
|
filter: { type: "string" },
|
|
5839
|
+
entities: { type: "string" },
|
|
5375
5840
|
phrase: { type: "string" },
|
|
5376
5841
|
contains: { type: "string" },
|
|
5377
5842
|
"max-per-document": { type: "number", min: 1 },
|
|
@@ -5398,12 +5863,25 @@ var dataSourcesSpecs = {
|
|
|
5398
5863
|
}
|
|
5399
5864
|
},
|
|
5400
5865
|
"datasources count": {
|
|
5401
|
-
usage: "Usage: remy-admin datasources count [--source <slug>] [--filter <k=v,...|json>] [--contains <words>] [--phrase <text>] [--candidate]",
|
|
5866
|
+
usage: "Usage: remy-admin datasources count [--source <slug>] [--filter <k=v,...|json>] [--entities <id,...>] [--contains <words>] [--phrase <text>] [--candidate]",
|
|
5867
|
+
flags: {
|
|
5868
|
+
source: { type: "string" },
|
|
5869
|
+
filter: { type: "string" },
|
|
5870
|
+
entities: { type: "string" },
|
|
5871
|
+
contains: { type: "string" },
|
|
5872
|
+
phrase: { type: "string" },
|
|
5873
|
+
candidate: { type: "boolean" }
|
|
5874
|
+
}
|
|
5875
|
+
},
|
|
5876
|
+
"datasources entities": {
|
|
5877
|
+
usage: "Usage: remy-admin datasources entities [--source <slug>] [--filter <k=v,...|json>] [--entities <id,...>] [--contains <words>] [--phrase <text>] [--limit <n>] [--candidate]",
|
|
5402
5878
|
flags: {
|
|
5403
5879
|
source: { type: "string" },
|
|
5404
5880
|
filter: { type: "string" },
|
|
5881
|
+
entities: { type: "string" },
|
|
5405
5882
|
contains: { type: "string" },
|
|
5406
5883
|
phrase: { type: "string" },
|
|
5884
|
+
limit: { type: "number", min: 1 },
|
|
5407
5885
|
candidate: { type: "boolean" }
|
|
5408
5886
|
}
|
|
5409
5887
|
},
|
|
@@ -5449,22 +5927,24 @@ async function dataSourcesAdd(ctx, a) {
|
|
|
5449
5927
|
const files = a.rest("file");
|
|
5450
5928
|
const slug = sourceOf(a);
|
|
5451
5929
|
const metadata = parseKeyValuePairs(a.str("metadata"), "metadata");
|
|
5930
|
+
const entities2 = parseIdList(a.str("entities"));
|
|
5452
5931
|
const results = [];
|
|
5453
5932
|
for (const file of files) {
|
|
5454
|
-
const abs =
|
|
5933
|
+
const abs = path6.isAbsolute(file) ? file : path6.join(WORKSPACE_DIR, file);
|
|
5455
5934
|
let bytes;
|
|
5456
5935
|
try {
|
|
5457
|
-
bytes =
|
|
5936
|
+
bytes = fs6.readFileSync(abs);
|
|
5458
5937
|
} catch (err) {
|
|
5459
5938
|
fatal(`Could not read file "${file}": ${err.message}`);
|
|
5460
5939
|
}
|
|
5461
|
-
const filename =
|
|
5940
|
+
const filename = path6.basename(file);
|
|
5462
5941
|
results.push(
|
|
5463
5942
|
await addDocument(ctx, {
|
|
5464
5943
|
slug,
|
|
5465
5944
|
filename,
|
|
5466
5945
|
content: bytes,
|
|
5467
5946
|
...metadata ? { metadata } : {},
|
|
5947
|
+
...entities2 ? { entities: entities2 } : {},
|
|
5468
5948
|
onProgress: progress
|
|
5469
5949
|
})
|
|
5470
5950
|
);
|
|
@@ -5535,6 +6015,7 @@ async function dataSourcesStatus(ctx, a) {
|
|
|
5535
6015
|
activeVersion: source.activeVersion,
|
|
5536
6016
|
candidate: source.candidate,
|
|
5537
6017
|
job: source.job,
|
|
6018
|
+
relink: source.relink,
|
|
5538
6019
|
failures: (failures?.documents ?? []).map(summarize),
|
|
5539
6020
|
moreFailures: !!failures?.nextCursor
|
|
5540
6021
|
});
|
|
@@ -5550,16 +6031,7 @@ async function dataSourcesRm(ctx, a) {
|
|
|
5550
6031
|
out({ deleted: documentId });
|
|
5551
6032
|
return;
|
|
5552
6033
|
}
|
|
5553
|
-
|
|
5554
|
-
if (rawFilter.trimStart().startsWith("{")) {
|
|
5555
|
-
try {
|
|
5556
|
-
filter = JSON.parse(rawFilter);
|
|
5557
|
-
} catch (err) {
|
|
5558
|
-
fatal(`--filter is not valid JSON: ${err.message}`);
|
|
5559
|
-
}
|
|
5560
|
-
} else {
|
|
5561
|
-
filter = { metadata: parseKeyValuePairs(rawFilter, "filter") };
|
|
5562
|
-
}
|
|
6034
|
+
const filter = documentSelectorOf(rawFilter);
|
|
5563
6035
|
const slug = sourceOf(a);
|
|
5564
6036
|
const result = await rmWhereAll(ctx, {
|
|
5565
6037
|
slug,
|
|
@@ -5614,6 +6086,24 @@ async function dataSourcesCount(ctx, a) {
|
|
|
5614
6086
|
})
|
|
5615
6087
|
);
|
|
5616
6088
|
}
|
|
6089
|
+
async function dataSourcesEntities(ctx, a) {
|
|
6090
|
+
const filter = filterFromFlags(a);
|
|
6091
|
+
const limit = a.num("limit");
|
|
6092
|
+
out(
|
|
6093
|
+
await entities(ctx, {
|
|
6094
|
+
slug: sourceOf(a),
|
|
6095
|
+
...filter ? { filter } : {},
|
|
6096
|
+
...limit !== void 0 ? { limit } : {},
|
|
6097
|
+
...a.bool("candidate") ? { candidate: true } : {}
|
|
6098
|
+
})
|
|
6099
|
+
);
|
|
6100
|
+
}
|
|
6101
|
+
function parseIdList(raw) {
|
|
6102
|
+
if (raw === void 0) {
|
|
6103
|
+
return void 0;
|
|
6104
|
+
}
|
|
6105
|
+
return raw.split(",").map((id) => id.trim()).filter((id) => id.length > 0);
|
|
6106
|
+
}
|
|
5617
6107
|
function filterFromFlags(a) {
|
|
5618
6108
|
let filter = {};
|
|
5619
6109
|
const raw = a.str("filter");
|
|
@@ -5631,6 +6121,10 @@ function filterFromFlags(a) {
|
|
|
5631
6121
|
}
|
|
5632
6122
|
}
|
|
5633
6123
|
}
|
|
6124
|
+
const entities2 = parseIdList(a.str("entities"));
|
|
6125
|
+
if (entities2?.length) {
|
|
6126
|
+
filter.entities = entities2;
|
|
6127
|
+
}
|
|
5634
6128
|
const phrase = a.str("phrase");
|
|
5635
6129
|
if (phrase) {
|
|
5636
6130
|
filter.phrase = phrase;
|
|
@@ -5641,29 +6135,6 @@ function filterFromFlags(a) {
|
|
|
5641
6135
|
}
|
|
5642
6136
|
return Object.keys(filter).length ? filter : void 0;
|
|
5643
6137
|
}
|
|
5644
|
-
function parseKeyValuePairs(raw, flag) {
|
|
5645
|
-
if (raw === void 0) {
|
|
5646
|
-
return void 0;
|
|
5647
|
-
}
|
|
5648
|
-
const pairs2 = {};
|
|
5649
|
-
for (const part of raw.split(",")) {
|
|
5650
|
-
const trimmed = part.trim();
|
|
5651
|
-
if (!trimmed) {
|
|
5652
|
-
continue;
|
|
5653
|
-
}
|
|
5654
|
-
const eq = trimmed.indexOf("=");
|
|
5655
|
-
if (eq <= 0) {
|
|
5656
|
-
fatal(`--${flag} entries must be key=value (got "${trimmed}").`);
|
|
5657
|
-
}
|
|
5658
|
-
const key = trimmed.slice(0, eq).trim();
|
|
5659
|
-
const value = trimmed.slice(eq + 1).trim();
|
|
5660
|
-
pairs2[key] = value === "true" ? true : value === "false" ? false : value !== "" && !Number.isNaN(Number(value)) ? Number(value) : value;
|
|
5661
|
-
}
|
|
5662
|
-
if (Object.keys(pairs2).length === 0) {
|
|
5663
|
-
fatal(`--${flag} needs at least one key=value pair.`);
|
|
5664
|
-
}
|
|
5665
|
-
return pairs2;
|
|
5666
|
-
}
|
|
5667
6138
|
function triState2(a, flag, key) {
|
|
5668
6139
|
const raw = a.str(flag);
|
|
5669
6140
|
if (raw === void 0) {
|
|
@@ -5890,6 +6361,7 @@ var dataSourcesHandlers = {
|
|
|
5890
6361
|
"datasources create": dataSourcesCreate,
|
|
5891
6362
|
"datasources config": dataSourcesConfig,
|
|
5892
6363
|
"datasources count": dataSourcesCount,
|
|
6364
|
+
"datasources entities": dataSourcesEntities,
|
|
5893
6365
|
"datasources move": dataSourcesMove,
|
|
5894
6366
|
"datasources revectorize": dataSourcesRevectorize,
|
|
5895
6367
|
"datasources promote": dataSourcesPromote,
|
|
@@ -5929,12 +6401,13 @@ Subcommands:
|
|
|
5929
6401
|
delete Delete a whole data source \u2014 documents, vectors and versions
|
|
5930
6402
|
|
|
5931
6403
|
Usage:
|
|
5932
|
-
remy-admin datasources add [--source <slug>] [--metadata <k=v,...>] [--wait] [--timeout <sec>] <file...>
|
|
6404
|
+
remy-admin datasources add [--source <slug>] [--metadata <k=v,...>] [--entities <id,...>] [--wait] [--timeout <sec>] <file...>
|
|
5933
6405
|
remy-admin datasources list
|
|
5934
6406
|
remy-admin datasources status [--source <slug>] [--status error] [--all]
|
|
5935
6407
|
remy-admin datasources rm [--source <slug>] (--document <id> | --filter <k=v,...|json>)
|
|
5936
6408
|
remy-admin datasources search [--source <slug>] [search options] <query>
|
|
5937
|
-
remy-admin datasources count [--source <slug>] [--filter <k=v,...|json>] [--contains <words>] [--phrase <text>] [--candidate]
|
|
6409
|
+
remy-admin datasources count [--source <slug>] [--filter <k=v,...|json>] [--entities <id,...>] [--contains <words>] [--phrase <text>] [--candidate]
|
|
6410
|
+
remy-admin datasources entities [--source <slug>] [--filter <k=v,...|json>] [--entities <id,...>] [--limit <n>] [--candidate]
|
|
5938
6411
|
remy-admin datasources create --source <slug> [--name <name>] [--placement <resource-id|shared>] [rebuild settings...]
|
|
5939
6412
|
remy-admin datasources config [--source <slug>] [--placement <resource-id|shared>] [settings...]
|
|
5940
6413
|
remy-admin datasources move [--source <slug>] --to <resource-id|shared> [--chains <n>] [--restart] [--wait] [--timeout <sec>]
|
|
@@ -5955,6 +6428,15 @@ Count:
|
|
|
5955
6428
|
count (none exists), and not the set search returns. The SDK's
|
|
5956
6429
|
\`Source.count(filter)\` is the same call for an app.
|
|
5957
6430
|
|
|
6431
|
+
Entities:
|
|
6432
|
+
A document can assert what it is about as your own ids (\`add --entities\`,
|
|
6433
|
+
a mapper's \`entities\`, a manifest line's \`entities\`), and every passage
|
|
6434
|
+
carries them. \`--entities a,b\` on search and count narrows to passages
|
|
6435
|
+
about any of them. \`entities\` lists which entities the matching passages
|
|
6436
|
+
are about, most first, with how many passages carry each (approximate, and
|
|
6437
|
+
passages, not documents): filter on one entity to see what appears beside
|
|
6438
|
+
it. The SDK's \`Source.entities({ filter, limit })\` is the same call.
|
|
6439
|
+
|
|
5958
6440
|
Search options:
|
|
5959
6441
|
--top-k <n> Results to return (default 5, max 50)
|
|
5960
6442
|
--mode <m> hybrid (default) | semantic | lexical. Lexical is
|
|
@@ -5963,11 +6445,12 @@ Search options:
|
|
|
5963
6445
|
--filter <k=v,...> Match document metadata set at add time. Values
|
|
5964
6446
|
coerce: true/false and numbers become typed.
|
|
5965
6447
|
Pass a JSON object for the full grammar:
|
|
5966
|
-
metadata, filename, documentIds,
|
|
5967
|
-
phrase \u2014 e.g. --filter '{"pages":{"max":3}}'.
|
|
6448
|
+
metadata, filename, documentIds, entities, pages,
|
|
6449
|
+
contains, phrase \u2014 e.g. --filter '{"pages":{"max":3}}'.
|
|
5968
6450
|
Metadata takes numeric ranges via {gte,lte}: store
|
|
5969
6451
|
dates as integers (YYYYMMDD or epoch seconds), then
|
|
5970
6452
|
--filter '{"metadata":{"date":{"gte":20250101}}}'
|
|
6453
|
+
--entities <id,...> Chunk must be about any of these entities
|
|
5971
6454
|
--phrase <text> Chunk must contain this exact word sequence
|
|
5972
6455
|
--contains <words> Chunk must contain ALL these words, any order
|
|
5973
6456
|
--max-per-document <n> Cap hits per document; backfills from others
|
|
@@ -6056,6 +6539,8 @@ Notes:
|
|
|
6056
6539
|
Re-adding an unchanged file is free: no upload, no re-embedding. Re-adding
|
|
6057
6540
|
with a different --metadata updates the tags in place, also free.
|
|
6058
6541
|
--metadata tags documents for search-time filtering (scalars, \u226416 keys).
|
|
6542
|
+
--entities names what a document is about, as your own ids (\u2264256, no spaces
|
|
6543
|
+
or commas); an empty --entities clears them. Also free on a re-add.
|
|
6059
6544
|
rm --filter removes every matching document in pages of a thousand: k=v
|
|
6060
6545
|
pairs match metadata; a JSON object takes the full selector \u2014 metadata,
|
|
6061
6546
|
filename, documentIds, externalIdPrefix (the key a job or connector
|
|
@@ -6095,7 +6580,7 @@ Examples:
|
|
|
6095
6580
|
remy-admin datasources revectorize --source archive-sample --max-chars 900 --wait
|
|
6096
6581
|
remy-admin datasources eval run --set <setId> --candidate --label small-chunks --wait
|
|
6097
6582
|
remy-admin datasources eval compare <runA> <runB>
|
|
6098
|
-
${dataSourceJobsHelp}${dataSourceConnectorsHelp}${dataSourceMappersHelp}${dataSourceEvalsHelp}`;
|
|
6583
|
+
${dataSourceJobsHelp}${dataSourceConnectorsHelp}${dataSourceMappersHelp}${dataSourceReadersHelp}${dataSourceEvalsHelp}${dataSourceDictionaryHelp}`;
|
|
6099
6584
|
|
|
6100
6585
|
// src/ops/voice.ts
|
|
6101
6586
|
function normalizeE164(input) {
|
|
@@ -6455,6 +6940,86 @@ Notes:
|
|
|
6455
6940
|
'remy-admin requests get <requestId>' for that call's input, output, stdout
|
|
6456
6941
|
and error. Client tools run in the browser, so they have no requestId.`;
|
|
6457
6942
|
|
|
6943
|
+
// src/ops/tasks.ts
|
|
6944
|
+
function list10(ctx, params = {}) {
|
|
6945
|
+
return call(
|
|
6946
|
+
ctx,
|
|
6947
|
+
"GET",
|
|
6948
|
+
`/_internal/v2/apps/${ctx.appId}/task-traces${qs(params)}`
|
|
6949
|
+
);
|
|
6950
|
+
}
|
|
6951
|
+
function get9(ctx, traceId) {
|
|
6952
|
+
return call(
|
|
6953
|
+
ctx,
|
|
6954
|
+
"GET",
|
|
6955
|
+
`/_internal/v2/apps/${ctx.appId}/task-traces/${seg(traceId)}`
|
|
6956
|
+
);
|
|
6957
|
+
}
|
|
6958
|
+
|
|
6959
|
+
// src/commands/tasks.ts
|
|
6960
|
+
var tasksSpecs = {
|
|
6961
|
+
"tasks list": {
|
|
6962
|
+
usage: "Usage: remy-admin tasks list [--limit 20] [--cursor <nextCursor>]",
|
|
6963
|
+
flags: {
|
|
6964
|
+
limit: { type: "number", min: 1, max: 100 },
|
|
6965
|
+
cursor: { type: "string" }
|
|
6966
|
+
}
|
|
6967
|
+
},
|
|
6968
|
+
"tasks get": {
|
|
6969
|
+
usage: "Usage: remy-admin tasks get <traceId>",
|
|
6970
|
+
positionals: [{ name: "traceId", required: true }]
|
|
6971
|
+
}
|
|
6972
|
+
};
|
|
6973
|
+
async function list11(ctx, a) {
|
|
6974
|
+
out(
|
|
6975
|
+
await list10(ctx, {
|
|
6976
|
+
limit: a.num("limit"),
|
|
6977
|
+
cursor: a.str("cursor")
|
|
6978
|
+
})
|
|
6979
|
+
);
|
|
6980
|
+
}
|
|
6981
|
+
async function get10(ctx, a) {
|
|
6982
|
+
out(await get9(ctx, a.req("traceId")));
|
|
6983
|
+
}
|
|
6984
|
+
var tasksHandlers = {
|
|
6985
|
+
"tasks list": list11,
|
|
6986
|
+
"tasks get": get10
|
|
6987
|
+
};
|
|
6988
|
+
var tasksHelp = `remy-admin tasks \u2014 Log of the app's task agents (runTask), kept 90 days.
|
|
6989
|
+
|
|
6990
|
+
Subcommands:
|
|
6991
|
+
list Every task run, newest started first (transcripts excluded)
|
|
6992
|
+
get One run with its full transcript
|
|
6993
|
+
|
|
6994
|
+
Usage:
|
|
6995
|
+
remy-admin tasks list [--limit 20] [--cursor <nextCursor>]
|
|
6996
|
+
remy-admin tasks get <traceId>
|
|
6997
|
+
|
|
6998
|
+
Notes:
|
|
6999
|
+
Transcripts are how you iterate on a task agent: after a run, read 'get' for
|
|
7000
|
+
what the model was given, what it decided each turn, and which tools ran with
|
|
7001
|
+
which arguments, then fix the prompt and tool descriptions from that
|
|
7002
|
+
evidence rather than from guesses. The id is 'result.traceId' from runTask(),
|
|
7003
|
+
and the list's 'traceId'. An unknown id is 'task_trace_not_found' (404).
|
|
7004
|
+
|
|
7005
|
+
In the list, 'outcome' says how the run ended: 'answered' (the last turn
|
|
7006
|
+
replied), 'in_progress', 'stopped' (it asked for tools and nothing followed),
|
|
7007
|
+
or 'error' (a model call failed). 'toolErrorCount' and 'hasTurnError' point at
|
|
7008
|
+
the runs worth opening, 'requestId' is the method execution that started the
|
|
7009
|
+
task, and 'devSession' is true for your own runs through the dev tunnel.
|
|
7010
|
+
'billingCost' is in nanodollars.
|
|
7011
|
+
|
|
7012
|
+
In a transcript, the first message is the task's input; 'assistant' messages
|
|
7013
|
+
are the model's turns (with 'turn', 'stopReason' and any 'thinking');
|
|
7014
|
+
'user' messages carrying 'toolCallId' are tool results. A method tool's
|
|
7015
|
+
result also carries a 'requestId' \u2014 pass it to
|
|
7016
|
+
'remy-admin requests get <requestId>' for that call's input, output, stdout
|
|
7017
|
+
and error.
|
|
7018
|
+
|
|
7019
|
+
Examples:
|
|
7020
|
+
remy-admin tasks list --limit 10
|
|
7021
|
+
remy-admin tasks get 0b9e\u2026`;
|
|
7022
|
+
|
|
6458
7023
|
// src/ops/events.ts
|
|
6459
7024
|
function channelsList(ctx, params = {}) {
|
|
6460
7025
|
return call(
|
|
@@ -7396,14 +7961,14 @@ async function resolveDomainId(ctx, direction, domain) {
|
|
|
7396
7961
|
}
|
|
7397
7962
|
return match.id;
|
|
7398
7963
|
}
|
|
7399
|
-
function
|
|
7964
|
+
function list12(ctx, params = {}) {
|
|
7400
7965
|
return call(
|
|
7401
7966
|
ctx,
|
|
7402
7967
|
"GET",
|
|
7403
7968
|
`/_internal/v2/apps/${ctx.appId}/outbound-email/messages${qs(params)}`
|
|
7404
7969
|
);
|
|
7405
7970
|
}
|
|
7406
|
-
function
|
|
7971
|
+
function get11(ctx, messageId) {
|
|
7407
7972
|
return call(
|
|
7408
7973
|
ctx,
|
|
7409
7974
|
"GET",
|
|
@@ -7595,7 +8160,7 @@ var emailSpecs = {
|
|
|
7595
8160
|
};
|
|
7596
8161
|
async function emailList(ctx, a) {
|
|
7597
8162
|
out(
|
|
7598
|
-
await
|
|
8163
|
+
await list12(ctx, {
|
|
7599
8164
|
status: a.str("status"),
|
|
7600
8165
|
kind: a.str("kind"),
|
|
7601
8166
|
recipient: a.str("recipient"),
|
|
@@ -7609,7 +8174,7 @@ async function emailList(ctx, a) {
|
|
|
7609
8174
|
);
|
|
7610
8175
|
}
|
|
7611
8176
|
async function emailGet(ctx, a) {
|
|
7612
|
-
out(await
|
|
8177
|
+
out(await get11(ctx, a.req("messageId")));
|
|
7613
8178
|
}
|
|
7614
8179
|
async function emailStats(ctx, a) {
|
|
7615
8180
|
out(await stats2(ctx, { start: a.str("start"), end: a.str("end") }));
|
|
@@ -7759,10 +8324,12 @@ Notes:
|
|
|
7759
8324
|
method run, errors) with 'requests get <id>'.
|
|
7760
8325
|
|
|
7761
8326
|
Custom domains \u2014 two independent directions:
|
|
7762
|
-
'domains' govern the From address
|
|
7763
|
-
dnsInstructions:
|
|
7764
|
-
|
|
7765
|
-
|
|
8327
|
+
'domains' govern the From address. 'add' returns
|
|
8328
|
+
dnsInstructions.records: the DNS records to publish, each
|
|
8329
|
+
marked required or not (on the cloud, three DKIM CNAMEs
|
|
8330
|
+
and a recommended SPF TXT) \u2014 hand these to the user to
|
|
8331
|
+
create at their DNS host, then 'verify <domain>' to
|
|
8332
|
+
re-check now.
|
|
7766
8333
|
'list' also returns effectiveSender: what the app currently
|
|
7767
8334
|
sends as, and which tier that address comes from.
|
|
7768
8335
|
'inbound-domains' receive mail at the user's own domain via one MX record
|
|
@@ -7771,7 +8338,7 @@ Custom domains \u2014 two independent directions:
|
|
|
7771
8338
|
with no setup; a custom inbound domain is optional polish.
|
|
7772
8339
|
|
|
7773
8340
|
uiStatus per domain: pending (records not confirmed yet \u2014 sending verification
|
|
7774
|
-
can take minutes after the
|
|
8341
|
+
can take minutes after the records resolve), verified, or action_needed (check
|
|
7775
8342
|
verificationErrors; sending verification expires unstarted after ~72h \u2014 fix
|
|
7776
8343
|
the records and 'verify' again).
|
|
7777
8344
|
|
|
@@ -7785,7 +8352,7 @@ Examples:
|
|
|
7785
8352
|
`;
|
|
7786
8353
|
|
|
7787
8354
|
// src/ops/cron.ts
|
|
7788
|
-
function
|
|
8355
|
+
function list13(ctx, params = {}) {
|
|
7789
8356
|
return call(
|
|
7790
8357
|
ctx,
|
|
7791
8358
|
"GET",
|
|
@@ -7814,7 +8381,7 @@ var cronSpecs = {
|
|
|
7814
8381
|
}
|
|
7815
8382
|
};
|
|
7816
8383
|
async function cronList(ctx, a) {
|
|
7817
|
-
out(await
|
|
8384
|
+
out(await list13(ctx, { runs: a.num("runs") }));
|
|
7818
8385
|
}
|
|
7819
8386
|
async function cronRun(ctx, a) {
|
|
7820
8387
|
out(await run2(ctx, a.req("route")));
|
|
@@ -7850,21 +8417,21 @@ Examples:
|
|
|
7850
8417
|
// src/ops/infra.ts
|
|
7851
8418
|
var DEFAULT_WAIT_TIMEOUT_MS4 = 10 * 60 * 1e3;
|
|
7852
8419
|
var POLL_MS5 = 3e3;
|
|
7853
|
-
function
|
|
8420
|
+
function base7(appId) {
|
|
7854
8421
|
return `/_internal/v2/apps/${appId}/infra`;
|
|
7855
8422
|
}
|
|
7856
|
-
function
|
|
8423
|
+
function list14(ctx, params) {
|
|
7857
8424
|
return call(
|
|
7858
8425
|
ctx,
|
|
7859
8426
|
"GET",
|
|
7860
|
-
`${
|
|
8427
|
+
`${base7(ctx.appId)}${params?.includeDestroyed ? "?includeDestroyed=true" : ""}`
|
|
7861
8428
|
);
|
|
7862
8429
|
}
|
|
7863
|
-
function
|
|
8430
|
+
function get12(ctx, params) {
|
|
7864
8431
|
return call(
|
|
7865
8432
|
ctx,
|
|
7866
8433
|
"GET",
|
|
7867
|
-
`${
|
|
8434
|
+
`${base7(ctx.appId)}/${encodeURIComponent(params.id)}`
|
|
7868
8435
|
);
|
|
7869
8436
|
}
|
|
7870
8437
|
function logs(ctx, params) {
|
|
@@ -7879,11 +8446,11 @@ function logs(ctx, params) {
|
|
|
7879
8446
|
return call(
|
|
7880
8447
|
ctx,
|
|
7881
8448
|
"GET",
|
|
7882
|
-
`${
|
|
8449
|
+
`${base7(ctx.appId)}/${encodeURIComponent(params.id)}/logs${search2 ? `?${search2}` : ""}`
|
|
7883
8450
|
);
|
|
7884
8451
|
}
|
|
7885
8452
|
function provision(ctx, params) {
|
|
7886
|
-
return call(ctx, "POST",
|
|
8453
|
+
return call(ctx, "POST", base7(ctx.appId), {
|
|
7887
8454
|
offeringId: params.offeringId,
|
|
7888
8455
|
...params.name ? { name: params.name } : {}
|
|
7889
8456
|
});
|
|
@@ -7892,28 +8459,28 @@ function hibernate(ctx, params) {
|
|
|
7892
8459
|
return call(
|
|
7893
8460
|
ctx,
|
|
7894
8461
|
"POST",
|
|
7895
|
-
`${
|
|
8462
|
+
`${base7(ctx.appId)}/${encodeURIComponent(params.id)}/hibernate`
|
|
7896
8463
|
);
|
|
7897
8464
|
}
|
|
7898
8465
|
function resume2(ctx, params) {
|
|
7899
8466
|
return call(
|
|
7900
8467
|
ctx,
|
|
7901
8468
|
"POST",
|
|
7902
|
-
`${
|
|
8469
|
+
`${base7(ctx.appId)}/${encodeURIComponent(params.id)}/resume`
|
|
7903
8470
|
);
|
|
7904
8471
|
}
|
|
7905
8472
|
function destroy(ctx, params) {
|
|
7906
8473
|
return call(
|
|
7907
8474
|
ctx,
|
|
7908
8475
|
"POST",
|
|
7909
|
-
`${
|
|
8476
|
+
`${base7(ctx.appId)}/${encodeURIComponent(params.id)}/destroy`
|
|
7910
8477
|
);
|
|
7911
8478
|
}
|
|
7912
8479
|
function resize(ctx, params) {
|
|
7913
8480
|
return call(
|
|
7914
8481
|
ctx,
|
|
7915
8482
|
"POST",
|
|
7916
|
-
`${
|
|
8483
|
+
`${base7(ctx.appId)}/${encodeURIComponent(params.id)}/resize`,
|
|
7917
8484
|
{ offeringId: params.offeringId }
|
|
7918
8485
|
);
|
|
7919
8486
|
}
|
|
@@ -7921,7 +8488,7 @@ function rename(ctx, params) {
|
|
|
7921
8488
|
return call(
|
|
7922
8489
|
ctx,
|
|
7923
8490
|
"POST",
|
|
7924
|
-
`${
|
|
8491
|
+
`${base7(ctx.appId)}/${encodeURIComponent(params.id)}/rename`,
|
|
7925
8492
|
{ name: params.name }
|
|
7926
8493
|
);
|
|
7927
8494
|
}
|
|
@@ -7930,7 +8497,7 @@ async function waitForPhase(ctx, params) {
|
|
|
7930
8497
|
const wanted = new Set(params.phases);
|
|
7931
8498
|
const arrived = (resource2) => wanted.has(resource2.phase) && (params.until?.(resource2) ?? true);
|
|
7932
8499
|
const outcome = await pollUntil(
|
|
7933
|
-
async () => (await
|
|
8500
|
+
async () => (await get12(ctx, { id: params.id })).resource,
|
|
7934
8501
|
(resource2) => arrived(resource2) || resource2.phase === "failed",
|
|
7935
8502
|
{
|
|
7936
8503
|
timeoutMs,
|
|
@@ -8045,10 +8612,10 @@ async function waitAndReport2(ctx, a, id, phases, summary2, until) {
|
|
|
8045
8612
|
}
|
|
8046
8613
|
}
|
|
8047
8614
|
async function infraList(ctx, a) {
|
|
8048
|
-
out(await
|
|
8615
|
+
out(await list14(ctx, { includeDestroyed: a.bool("include-destroyed") }));
|
|
8049
8616
|
}
|
|
8050
8617
|
async function infraGet(ctx, a) {
|
|
8051
|
-
out(await
|
|
8618
|
+
out(await get12(ctx, { id: a.req("id") }));
|
|
8052
8619
|
}
|
|
8053
8620
|
var FOLLOW_POLL_MS = 4e3;
|
|
8054
8621
|
async function infraLogs(ctx, a) {
|
|
@@ -8490,9 +9057,12 @@ var SPECS = {
|
|
|
8490
9057
|
...dataSourceJobsSpecs,
|
|
8491
9058
|
...dataSourceConnectorsSpecs,
|
|
8492
9059
|
...dataSourceEvalsSpecs,
|
|
9060
|
+
...dataSourceDictionarySpecs,
|
|
8493
9061
|
...dataSourceMappersSpecs,
|
|
9062
|
+
...dataSourceReadersSpecs,
|
|
8494
9063
|
...voiceSpecs,
|
|
8495
9064
|
...agentSpecs,
|
|
9065
|
+
...tasksSpecs,
|
|
8496
9066
|
...eventsSpecs,
|
|
8497
9067
|
...jewelsSpecs,
|
|
8498
9068
|
...settingsSpecs,
|
|
@@ -8520,9 +9090,12 @@ var HANDLERS = {
|
|
|
8520
9090
|
...dataSourceJobsHandlers,
|
|
8521
9091
|
...dataSourceConnectorsHandlers,
|
|
8522
9092
|
...dataSourceEvalsHandlers,
|
|
9093
|
+
...dataSourceDictionaryHandlers,
|
|
8523
9094
|
...dataSourceMappersHandlers,
|
|
9095
|
+
...dataSourceReadersHandlers,
|
|
8524
9096
|
...voiceHandlers,
|
|
8525
9097
|
...agentHandlers,
|
|
9098
|
+
...tasksHandlers,
|
|
8526
9099
|
...eventsHandlers,
|
|
8527
9100
|
...jewelsHandlers,
|
|
8528
9101
|
...settingsHandlers,
|
|
@@ -8549,6 +9122,7 @@ var GROUP_HELP = {
|
|
|
8549
9122
|
datasources: dataSourcesHelp,
|
|
8550
9123
|
voice: voiceHelp,
|
|
8551
9124
|
agent: agentHelp,
|
|
9125
|
+
tasks: tasksHelp,
|
|
8552
9126
|
events: eventsHelp,
|
|
8553
9127
|
jewels: jewelsHelp,
|
|
8554
9128
|
settings: settingsHelp,
|
|
@@ -8559,8 +9133,8 @@ var GROUP_HELP = {
|
|
|
8559
9133
|
};
|
|
8560
9134
|
|
|
8561
9135
|
// src/ctx.ts
|
|
8562
|
-
import
|
|
8563
|
-
import
|
|
9136
|
+
import fs7 from "fs";
|
|
9137
|
+
import path7 from "path";
|
|
8564
9138
|
|
|
8565
9139
|
// src/parseJsonConfig.ts
|
|
8566
9140
|
import JSON5 from "json5";
|
|
@@ -8589,10 +9163,10 @@ function parseJsonConfig(raw) {
|
|
|
8589
9163
|
// src/ctx.ts
|
|
8590
9164
|
var DEFAULT_BASE_URL = "https://api.mindstudio.ai";
|
|
8591
9165
|
function loadWorkspaceAppId(workspaceDir = WORKSPACE_DIR) {
|
|
8592
|
-
const manifestPath =
|
|
9166
|
+
const manifestPath = path7.join(workspaceDir, "mindstudio.json");
|
|
8593
9167
|
let raw;
|
|
8594
9168
|
try {
|
|
8595
|
-
raw =
|
|
9169
|
+
raw = fs7.readFileSync(manifestPath, "utf-8");
|
|
8596
9170
|
} catch (err) {
|
|
8597
9171
|
if (err.code === "ENOENT") {
|
|
8598
9172
|
throw new Error(`mindstudio.json not found at ${manifestPath}`);
|
|
@@ -8632,6 +9206,7 @@ Commands:
|
|
|
8632
9206
|
datasources Build and query searchable document corpora (RAG)
|
|
8633
9207
|
voice Phone numbers, voice call log + transcripts, voice policy settings
|
|
8634
9208
|
agent Agent (chat) conversation log + transcripts
|
|
9209
|
+
tasks Task agent (runTask) log + transcripts
|
|
8635
9210
|
events Realtime events \u2014 live tail, test publish, channel activity
|
|
8636
9211
|
jewels Monitor jewel shadowing; review + approve the proposal queue
|
|
8637
9212
|
settings App settings \u2014 signup allowlist, test accounts, embed origins, toggles
|
|
@@ -8647,7 +9222,7 @@ with a dash, use --name=value; to pass a positional beginning with a dash, put
|
|
|
8647
9222
|
-- before it.
|
|
8648
9223
|
|
|
8649
9224
|
All output is JSON. Configuration is read from environment variables
|
|
8650
|
-
(MINDSTUDIO_API_KEY,
|
|
9225
|
+
(MINDSTUDIO_API_KEY, MINDSTUDIO_BASE_URL) and mindstudio.json (appId).`;
|
|
8651
9226
|
var GROUPS = [
|
|
8652
9227
|
"requests",
|
|
8653
9228
|
"crashes",
|
|
@@ -8666,6 +9241,7 @@ var GROUPS = [
|
|
|
8666
9241
|
"datasources",
|
|
8667
9242
|
"voice",
|
|
8668
9243
|
"agent",
|
|
9244
|
+
"tasks",
|
|
8669
9245
|
"events",
|
|
8670
9246
|
"jewels",
|
|
8671
9247
|
"settings",
|
|
@@ -8763,7 +9339,7 @@ async function main() {
|
|
|
8763
9339
|
apiKey,
|
|
8764
9340
|
appId: appIdOverride ?? loadWorkspaceAppId(),
|
|
8765
9341
|
originAppId,
|
|
8766
|
-
baseUrl: process.env["
|
|
9342
|
+
baseUrl: process.env["MINDSTUDIO_BASE_URL"] || DEFAULT_BASE_URL
|
|
8767
9343
|
};
|
|
8768
9344
|
return HANDLERS[route.key](ctx, a);
|
|
8769
9345
|
}
|