@stackbone/sdk 0.1.0-alpha.0 → 0.1.0-alpha.2
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/CHANGELOG.md +64 -0
- package/README.md +13 -12
- package/index.cjs +186 -242
- package/index.cjs.map +1 -1
- package/index.d.cts +73 -15
- package/index.d.ts +73 -15
- package/index.js +186 -242
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/stackbone-sdk-0.1.0-alpha.2.tgz +0 -0
- package/stackbone-sdk-0.1.0-alpha.0.tgz +0 -0
package/index.js
CHANGED
|
@@ -1786,9 +1786,9 @@ var nanoid = /^[a-zA-Z0-9_-]{21}$/;
|
|
|
1786
1786
|
var duration = /^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/;
|
|
1787
1787
|
var extendedDuration = /^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/;
|
|
1788
1788
|
var guid = /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/;
|
|
1789
|
-
var uuid = /* @__PURE__ */ __name((
|
|
1790
|
-
if (!
|
|
1791
|
-
return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${
|
|
1789
|
+
var uuid = /* @__PURE__ */ __name((version3) => {
|
|
1790
|
+
if (!version3) return /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/;
|
|
1791
|
+
return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${version3}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`);
|
|
1792
1792
|
}, "uuid");
|
|
1793
1793
|
var uuid4 = /* @__PURE__ */ uuid(4);
|
|
1794
1794
|
var uuid6 = /* @__PURE__ */ uuid(6);
|
|
@@ -14972,10 +14972,10 @@ function fromJSONSchema(schema, params) {
|
|
|
14972
14972
|
if (typeof schema === "boolean") {
|
|
14973
14973
|
return schema ? z.any() : z.never();
|
|
14974
14974
|
}
|
|
14975
|
-
const
|
|
14975
|
+
const version3 = detectVersion(schema, params?.defaultTarget);
|
|
14976
14976
|
const defs = schema.$defs || schema.definitions || {};
|
|
14977
14977
|
const ctx = {
|
|
14978
|
-
version:
|
|
14978
|
+
version: version3,
|
|
14979
14979
|
defs,
|
|
14980
14980
|
refs: /* @__PURE__ */ new Map(),
|
|
14981
14981
|
processing: /* @__PURE__ */ new Set(),
|
|
@@ -15553,6 +15553,13 @@ external_exports.object({
|
|
|
15553
15553
|
nextCursor: external_exports.string().nullable(),
|
|
15554
15554
|
prevCursor: external_exports.string().nullable()
|
|
15555
15555
|
});
|
|
15556
|
+
external_exports.object({
|
|
15557
|
+
fxtId: external_exports.uuid()
|
|
15558
|
+
});
|
|
15559
|
+
external_exports.object({
|
|
15560
|
+
input: jsonObject().nullable(),
|
|
15561
|
+
output: jsonObject().nullable()
|
|
15562
|
+
});
|
|
15556
15563
|
|
|
15557
15564
|
// ../validators/src/lib/auth/session.ts
|
|
15558
15565
|
var sessionUserSchema = external_exports.object({
|
|
@@ -16637,6 +16644,34 @@ function pickDefinedAsStrings(source) {
|
|
|
16637
16644
|
}
|
|
16638
16645
|
__name(pickDefinedAsStrings, "pickDefinedAsStrings");
|
|
16639
16646
|
|
|
16647
|
+
// src/lib/facade-helpers.ts
|
|
16648
|
+
function remapHttpNotFound(code, domainCode, message, meta3) {
|
|
16649
|
+
if (code !== "http_not_found") return null;
|
|
16650
|
+
const error48 = {
|
|
16651
|
+
code: domainCode,
|
|
16652
|
+
message
|
|
16653
|
+
};
|
|
16654
|
+
if (meta3) error48.meta = meta3;
|
|
16655
|
+
return err(error48);
|
|
16656
|
+
}
|
|
16657
|
+
__name(remapHttpNotFound, "remapHttpNotFound");
|
|
16658
|
+
function validateStringArray(values, field, errorCode) {
|
|
16659
|
+
if (!Array.isArray(values) || values.length === 0) {
|
|
16660
|
+
return err({
|
|
16661
|
+
code: errorCode,
|
|
16662
|
+
message: `\`${field}\` must be a non-empty array.`
|
|
16663
|
+
});
|
|
16664
|
+
}
|
|
16665
|
+
if (values.some((v) => typeof v !== "string" || !v.trim())) {
|
|
16666
|
+
return err({
|
|
16667
|
+
code: errorCode,
|
|
16668
|
+
message: `\`${field}[*]\` must be non-empty strings.`
|
|
16669
|
+
});
|
|
16670
|
+
}
|
|
16671
|
+
return null;
|
|
16672
|
+
}
|
|
16673
|
+
__name(validateStringArray, "validateStringArray");
|
|
16674
|
+
|
|
16640
16675
|
// src/facades/config/config.ts
|
|
16641
16676
|
var ConfigFacade = class {
|
|
16642
16677
|
static {
|
|
@@ -16658,7 +16693,11 @@ var ConfigFacade = class {
|
|
|
16658
16693
|
const gateResult = await this._gate();
|
|
16659
16694
|
if (gateResult.error) return err(gateResult.error);
|
|
16660
16695
|
const result = await this._http.get(`/api/config/${encodeURIComponent(key)}`);
|
|
16661
|
-
if (result.error)
|
|
16696
|
+
if (result.error) {
|
|
16697
|
+
return remapHttpNotFound(result.error.code, "config_not_found", `Config key \`${key}\` is not set for this agent.`, {
|
|
16698
|
+
key
|
|
16699
|
+
}) ?? result;
|
|
16700
|
+
}
|
|
16662
16701
|
return ok(result.data.value);
|
|
16663
16702
|
}
|
|
16664
16703
|
/**
|
|
@@ -16668,18 +16707,8 @@ var ConfigFacade = class {
|
|
|
16668
16707
|
* is `Partial<T>`).
|
|
16669
16708
|
*/
|
|
16670
16709
|
async getMany(keys) {
|
|
16671
|
-
|
|
16672
|
-
|
|
16673
|
-
code: "config_invalid_request",
|
|
16674
|
-
message: "`keys` must be a non-empty array."
|
|
16675
|
-
});
|
|
16676
|
-
}
|
|
16677
|
-
if (keys.some((k) => !k.trim())) {
|
|
16678
|
-
return err({
|
|
16679
|
-
code: "config_invalid_request",
|
|
16680
|
-
message: "`keys[*]` must be non-empty strings."
|
|
16681
|
-
});
|
|
16682
|
-
}
|
|
16710
|
+
const invalid = validateStringArray(keys, "keys", "config_invalid_request");
|
|
16711
|
+
if (invalid) return invalid;
|
|
16683
16712
|
const gateResult = await this._gate();
|
|
16684
16713
|
if (gateResult.error) return err(gateResult.error);
|
|
16685
16714
|
const result = await this._http.get("/api/config", {
|
|
@@ -16698,17 +16727,6 @@ var ConfigFacade = class {
|
|
|
16698
16727
|
return ok(values);
|
|
16699
16728
|
}
|
|
16700
16729
|
};
|
|
16701
|
-
function remapNotFound(code, key) {
|
|
16702
|
-
if (code !== "http_not_found") return null;
|
|
16703
|
-
return err({
|
|
16704
|
-
code: "config_not_found",
|
|
16705
|
-
message: `Config key \`${key}\` is not set for this agent.`,
|
|
16706
|
-
meta: {
|
|
16707
|
-
key
|
|
16708
|
-
}
|
|
16709
|
-
});
|
|
16710
|
-
}
|
|
16711
|
-
__name(remapNotFound, "remapNotFound");
|
|
16712
16730
|
|
|
16713
16731
|
// src/facades/connections/connections.ts
|
|
16714
16732
|
var ConnectionsFacade = class {
|
|
@@ -16794,7 +16812,11 @@ var SecretsFacade = class {
|
|
|
16794
16812
|
const gateResult = await this._gate();
|
|
16795
16813
|
if (gateResult.error) return err(gateResult.error);
|
|
16796
16814
|
const result = await this._http.get(`/api/secrets/${encodeURIComponent(name)}`);
|
|
16797
|
-
if (result.error)
|
|
16815
|
+
if (result.error) {
|
|
16816
|
+
return remapHttpNotFound(result.error.code, "secrets_not_found", `Secret \`${name}\` is not registered for this organization.`, {
|
|
16817
|
+
name
|
|
16818
|
+
}) ?? result;
|
|
16819
|
+
}
|
|
16798
16820
|
if (typeof result.data.value !== "string") {
|
|
16799
16821
|
return err({
|
|
16800
16822
|
code: "secrets_invalid_response",
|
|
@@ -16807,23 +16829,13 @@ var SecretsFacade = class {
|
|
|
16807
16829
|
return ok(result.data.value);
|
|
16808
16830
|
}
|
|
16809
16831
|
/**
|
|
16810
|
-
* Names absent from the
|
|
16832
|
+
* Names absent from the organization come back as omissions in the response —
|
|
16811
16833
|
* the returned map only contains entries the control plane actually has.
|
|
16812
16834
|
* Callers that need "all-or-nothing" semantics should diff the keys.
|
|
16813
16835
|
*/
|
|
16814
16836
|
async getMany(names) {
|
|
16815
|
-
|
|
16816
|
-
|
|
16817
|
-
code: "secrets_invalid_request",
|
|
16818
|
-
message: "`names` must be a non-empty array."
|
|
16819
|
-
});
|
|
16820
|
-
}
|
|
16821
|
-
if (names.some((n) => !n.trim())) {
|
|
16822
|
-
return err({
|
|
16823
|
-
code: "secrets_invalid_request",
|
|
16824
|
-
message: "`names[*]` must be non-empty strings."
|
|
16825
|
-
});
|
|
16826
|
-
}
|
|
16837
|
+
const invalid = validateStringArray(names, "names", "secrets_invalid_request");
|
|
16838
|
+
if (invalid) return invalid;
|
|
16827
16839
|
const gateResult = await this._gate();
|
|
16828
16840
|
if (gateResult.error) return err(gateResult.error);
|
|
16829
16841
|
const result = await this._http.get("/api/secrets", {
|
|
@@ -16842,17 +16854,6 @@ var SecretsFacade = class {
|
|
|
16842
16854
|
return ok(values);
|
|
16843
16855
|
}
|
|
16844
16856
|
};
|
|
16845
|
-
function remapNotFound2(code, name) {
|
|
16846
|
-
if (code !== "http_not_found") return null;
|
|
16847
|
-
return err({
|
|
16848
|
-
code: "secrets_not_found",
|
|
16849
|
-
message: `Secret \`${name}\` is not registered for this workspace.`,
|
|
16850
|
-
meta: {
|
|
16851
|
-
name
|
|
16852
|
-
}
|
|
16853
|
-
});
|
|
16854
|
-
}
|
|
16855
|
-
__name(remapNotFound2, "remapNotFound");
|
|
16856
16857
|
|
|
16857
16858
|
// src/lib/http-client.ts
|
|
16858
16859
|
var RETRYABLE_STATUS = /* @__PURE__ */ new Set([
|
|
@@ -17735,6 +17736,11 @@ async function aggregateRunCost(runId, options) {
|
|
|
17735
17736
|
};
|
|
17736
17737
|
}
|
|
17737
17738
|
__name(aggregateRunCost, "aggregateRunCost");
|
|
17739
|
+
|
|
17740
|
+
// package.json
|
|
17741
|
+
var version2 = "0.1.0-alpha.2";
|
|
17742
|
+
|
|
17743
|
+
// src/observability/logger.ts
|
|
17738
17744
|
var LOG_LEVELS = {
|
|
17739
17745
|
trace: 10,
|
|
17740
17746
|
debug: 20,
|
|
@@ -17948,7 +17954,7 @@ var OtlpHttpDestination = class OtlpHttpDestination2 {
|
|
|
17948
17954
|
};
|
|
17949
17955
|
var SDK_SCOPE = {
|
|
17950
17956
|
name: "@stackbone/sdk",
|
|
17951
|
-
version:
|
|
17957
|
+
version: version2
|
|
17952
17958
|
};
|
|
17953
17959
|
function buildOtlpLogsBody(records, resourceAttributes) {
|
|
17954
17960
|
return {
|
|
@@ -17981,11 +17987,12 @@ function toOtlpLogRecord(record2) {
|
|
|
17981
17987
|
};
|
|
17982
17988
|
}
|
|
17983
17989
|
__name(toOtlpLogRecord, "toOtlpLogRecord");
|
|
17990
|
+
var SEVERITY_TEXT_BY_LEVEL = Object.fromEntries(Object.entries(LOG_LEVELS).map(([name, value]) => [
|
|
17991
|
+
value,
|
|
17992
|
+
name.toUpperCase()
|
|
17993
|
+
]));
|
|
17984
17994
|
function severityText(level) {
|
|
17985
|
-
|
|
17986
|
-
if (value === level) return name.toUpperCase();
|
|
17987
|
-
}
|
|
17988
|
-
return "INFO";
|
|
17995
|
+
return SEVERITY_TEXT_BY_LEVEL[level] ?? "INFO";
|
|
17989
17996
|
}
|
|
17990
17997
|
__name(severityText, "severityText");
|
|
17991
17998
|
function toOtlpAttributes(attrs) {
|
|
@@ -18113,7 +18120,7 @@ var RunStepsSpanProcessor = class {
|
|
|
18113
18120
|
this.intervalMs = options.flushIntervalMs ?? DEFAULT_INTERVAL_MS2;
|
|
18114
18121
|
this.resolveStepType = options.resolveStepType ?? defaultStepTypeResolver;
|
|
18115
18122
|
this.newId = options.newId ?? randomUUID;
|
|
18116
|
-
this.connectionString = options.connectionString ?? process.env["
|
|
18123
|
+
this.connectionString = options.connectionString ?? process.env["STACKBONE_POSTGRES_URL"];
|
|
18117
18124
|
if (options.sql) {
|
|
18118
18125
|
this.sql = options.sql;
|
|
18119
18126
|
this.ownsSql = false;
|
|
@@ -18153,11 +18160,11 @@ var RunStepsSpanProcessor = class {
|
|
|
18153
18160
|
}
|
|
18154
18161
|
}
|
|
18155
18162
|
buildRow(span) {
|
|
18156
|
-
const runId = readString(span.attributes[RUN_ID_ATTRIBUTE]);
|
|
18157
|
-
if (!runId) return null;
|
|
18158
18163
|
const spanId = span.spanContext().spanId;
|
|
18159
18164
|
const stepId = this.stepIdBySpanId.get(spanId) ?? this.newId();
|
|
18160
18165
|
this.stepIdBySpanId.delete(spanId);
|
|
18166
|
+
const runId = readString(span.attributes[RUN_ID_ATTRIBUTE]);
|
|
18167
|
+
if (!runId) return null;
|
|
18161
18168
|
const parentSpanId = span.parentSpanContext?.spanId ?? span.parentSpanId ?? null;
|
|
18162
18169
|
const parentStepId = parentSpanId ? this.stepIdBySpanId.get(parentSpanId) ?? null : null;
|
|
18163
18170
|
const startedAt = formatHrTime(span.startTime);
|
|
@@ -18297,7 +18304,7 @@ var ObservabilityModule = class {
|
|
|
18297
18304
|
if (!this._processor) {
|
|
18298
18305
|
const merged = {
|
|
18299
18306
|
...options,
|
|
18300
|
-
connectionString: options.connectionString ?? this._resolved.config.databaseUrl ?? this._resolved.env["
|
|
18307
|
+
connectionString: options.connectionString ?? this._resolved.config.databaseUrl ?? this._resolved.env["STACKBONE_POSTGRES_URL"]
|
|
18301
18308
|
};
|
|
18302
18309
|
this._processor = new RunStepsSpanProcessor(merged);
|
|
18303
18310
|
}
|
|
@@ -18356,7 +18363,7 @@ var ObservabilityModule = class {
|
|
|
18356
18363
|
if (!sql) {
|
|
18357
18364
|
return err({
|
|
18358
18365
|
code: "database_url_missing",
|
|
18359
|
-
message: "Cannot reach the agent Postgres \u2014 set `
|
|
18366
|
+
message: "Cannot reach the agent Postgres \u2014 set `STACKBONE_POSTGRES_URL` in the container or pass `databaseUrl` to `createClient({...})`."
|
|
18360
18367
|
});
|
|
18361
18368
|
}
|
|
18362
18369
|
try {
|
|
@@ -18377,7 +18384,7 @@ var ObservabilityModule = class {
|
|
|
18377
18384
|
// don't pay the dep cost.
|
|
18378
18385
|
async resolveSql() {
|
|
18379
18386
|
if (this._sqlResolved) return this._sql;
|
|
18380
|
-
const connectionString = this._resolved.config.databaseUrl ?? this._resolved.env["
|
|
18387
|
+
const connectionString = this._resolved.config.databaseUrl ?? this._resolved.env["STACKBONE_POSTGRES_URL"];
|
|
18381
18388
|
if (!connectionString) {
|
|
18382
18389
|
this._sqlResolved = true;
|
|
18383
18390
|
return null;
|
|
@@ -18607,6 +18614,41 @@ function isUnsupportedModelError(error48) {
|
|
|
18607
18614
|
}
|
|
18608
18615
|
__name(isUnsupportedModelError, "isUnsupportedModelError");
|
|
18609
18616
|
|
|
18617
|
+
// src/modules/rag/errors.ts
|
|
18618
|
+
var PG_UNDEFINED_TABLE = "42P01";
|
|
18619
|
+
var RAG_SCHEMA_MISSING_HINT = "run `stackbone db migrate add-rag` and `stackbone db migrate up`";
|
|
18620
|
+
function isTaggedError(cause) {
|
|
18621
|
+
return cause instanceof Error;
|
|
18622
|
+
}
|
|
18623
|
+
__name(isTaggedError, "isTaggedError");
|
|
18624
|
+
function toRagError(cause, message, fallbackCode = "rag_error") {
|
|
18625
|
+
if (isTaggedError(cause) && cause.code === PG_UNDEFINED_TABLE) {
|
|
18626
|
+
return {
|
|
18627
|
+
code: "rag_schema_missing",
|
|
18628
|
+
message: `RAG tables are not installed \u2014 ${RAG_SCHEMA_MISSING_HINT}.`,
|
|
18629
|
+
cause,
|
|
18630
|
+
meta: {
|
|
18631
|
+
hint: RAG_SCHEMA_MISSING_HINT
|
|
18632
|
+
}
|
|
18633
|
+
};
|
|
18634
|
+
}
|
|
18635
|
+
if (isTaggedError(cause)) {
|
|
18636
|
+
const error48 = {
|
|
18637
|
+
code: cause.code ?? fallbackCode,
|
|
18638
|
+
message: `${message}: ${cause.message}`,
|
|
18639
|
+
cause
|
|
18640
|
+
};
|
|
18641
|
+
if (cause.meta) error48.meta = cause.meta;
|
|
18642
|
+
return error48;
|
|
18643
|
+
}
|
|
18644
|
+
return {
|
|
18645
|
+
code: fallbackCode,
|
|
18646
|
+
message,
|
|
18647
|
+
cause
|
|
18648
|
+
};
|
|
18649
|
+
}
|
|
18650
|
+
__name(toRagError, "toRagError");
|
|
18651
|
+
|
|
18610
18652
|
// src/modules/rag/jobs.ts
|
|
18611
18653
|
function createSqlJobWriter(sql) {
|
|
18612
18654
|
return {
|
|
@@ -18632,7 +18674,7 @@ function createSqlJobWriter(sql) {
|
|
|
18632
18674
|
jobId: row.id
|
|
18633
18675
|
});
|
|
18634
18676
|
} catch (cause) {
|
|
18635
|
-
return err(
|
|
18677
|
+
return err(toRagError(cause, "Job start failed", "rag_jobs_error"));
|
|
18636
18678
|
}
|
|
18637
18679
|
},
|
|
18638
18680
|
async progress({ jobId, processedChunks, totalChunks, currentDocument }) {
|
|
@@ -18671,7 +18713,7 @@ function createSqlJobWriter(sql) {
|
|
|
18671
18713
|
},
|
|
18672
18714
|
async isCancelled({ jobId }) {
|
|
18673
18715
|
const rows = await sql`
|
|
18674
|
-
SELECT
|
|
18716
|
+
SELECT status FROM stackbone_rag_jobs WHERE id = ${jobId} LIMIT 1
|
|
18675
18717
|
`;
|
|
18676
18718
|
return rows[0]?.status === "cancelled";
|
|
18677
18719
|
}
|
|
@@ -18679,10 +18721,6 @@ function createSqlJobWriter(sql) {
|
|
|
18679
18721
|
}
|
|
18680
18722
|
__name(createSqlJobWriter, "createSqlJobWriter");
|
|
18681
18723
|
async function ensureCollection(sql, name) {
|
|
18682
|
-
const existing = await sql`
|
|
18683
|
-
SELECT id FROM stackbone_rag_collections WHERE name = ${name} LIMIT 1
|
|
18684
|
-
`;
|
|
18685
|
-
if (existing[0]) return existing[0].id;
|
|
18686
18724
|
const inserted = await sql`
|
|
18687
18725
|
INSERT INTO stackbone_rag_collections (name) VALUES (${name})
|
|
18688
18726
|
ON CONFLICT (name) DO UPDATE SET name = EXCLUDED.name
|
|
@@ -18690,37 +18728,11 @@ async function ensureCollection(sql, name) {
|
|
|
18690
18728
|
`;
|
|
18691
18729
|
const row = inserted[0];
|
|
18692
18730
|
if (!row) {
|
|
18693
|
-
throw new Error(`stackbone_rag_collections
|
|
18731
|
+
throw new Error(`stackbone_rag_collections upsert returned no row for ${name}`);
|
|
18694
18732
|
}
|
|
18695
18733
|
return row.id;
|
|
18696
18734
|
}
|
|
18697
18735
|
__name(ensureCollection, "ensureCollection");
|
|
18698
|
-
function toJobsError(cause, message) {
|
|
18699
|
-
if (cause instanceof Error) {
|
|
18700
|
-
const tagged = cause;
|
|
18701
|
-
if (tagged.code === "42P01") {
|
|
18702
|
-
return {
|
|
18703
|
-
code: "rag_schema_missing",
|
|
18704
|
-
message: "RAG tables are not installed \u2014 run `stackbone db migrate add-rag` and `stackbone db migrate up`.",
|
|
18705
|
-
cause,
|
|
18706
|
-
meta: {
|
|
18707
|
-
hint: "run `stackbone db migrate add-rag` and `stackbone db migrate up`"
|
|
18708
|
-
}
|
|
18709
|
-
};
|
|
18710
|
-
}
|
|
18711
|
-
return {
|
|
18712
|
-
code: tagged.code ?? "rag_jobs_error",
|
|
18713
|
-
message: `${message}: ${cause.message}`,
|
|
18714
|
-
cause
|
|
18715
|
-
};
|
|
18716
|
-
}
|
|
18717
|
-
return {
|
|
18718
|
-
code: "rag_jobs_error",
|
|
18719
|
-
message,
|
|
18720
|
-
cause
|
|
18721
|
-
};
|
|
18722
|
-
}
|
|
18723
|
-
__name(toJobsError, "toJobsError");
|
|
18724
18736
|
var PDF_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
18725
18737
|
"application/pdf",
|
|
18726
18738
|
"application/x-pdf"
|
|
@@ -18780,10 +18792,12 @@ __name(looksLikePdf, "looksLikePdf");
|
|
|
18780
18792
|
var DEFAULT_NAMESPACE = "default";
|
|
18781
18793
|
var META_KEY_DIMENSIONS = "dimensions";
|
|
18782
18794
|
var META_KEY_DISTANCE = "distance";
|
|
18795
|
+
var schemaVerifiedDimensions = /* @__PURE__ */ new WeakMap();
|
|
18783
18796
|
async function ensureSchema(sql, dimensions) {
|
|
18784
18797
|
if (!Number.isInteger(dimensions) || dimensions <= 0 || dimensions > 8192) {
|
|
18785
18798
|
throw new Error(`rag.ensureSchema: invalid dimensions ${dimensions}. Must be a positive integer <= 8192.`);
|
|
18786
18799
|
}
|
|
18800
|
+
if (schemaVerifiedDimensions.get(sql) === dimensions) return;
|
|
18787
18801
|
const existing = await sql`
|
|
18788
18802
|
SELECT value::int AS value FROM _rag_meta WHERE key = ${META_KEY_DIMENSIONS}
|
|
18789
18803
|
`.catch(() => []);
|
|
@@ -18798,6 +18812,7 @@ async function ensureSchema(sql, dimensions) {
|
|
|
18798
18812
|
};
|
|
18799
18813
|
throw error48;
|
|
18800
18814
|
}
|
|
18815
|
+
schemaVerifiedDimensions.set(sql, dimensions);
|
|
18801
18816
|
return;
|
|
18802
18817
|
}
|
|
18803
18818
|
await sql.begin(async (tx) => {
|
|
@@ -18817,6 +18832,7 @@ async function ensureSchema(sql, dimensions) {
|
|
|
18817
18832
|
ON CONFLICT (key) DO NOTHING
|
|
18818
18833
|
`;
|
|
18819
18834
|
});
|
|
18835
|
+
schemaVerifiedDimensions.set(sql, dimensions);
|
|
18820
18836
|
}
|
|
18821
18837
|
__name(ensureSchema, "ensureSchema");
|
|
18822
18838
|
async function reset(sql) {
|
|
@@ -18824,29 +18840,31 @@ async function reset(sql) {
|
|
|
18824
18840
|
await tx`DROP TABLE IF EXISTS rag_chunks`;
|
|
18825
18841
|
await tx`DROP TABLE IF EXISTS _rag_meta`;
|
|
18826
18842
|
});
|
|
18843
|
+
schemaVerifiedDimensions.delete(sql);
|
|
18827
18844
|
}
|
|
18828
18845
|
__name(reset, "reset");
|
|
18829
|
-
async function
|
|
18846
|
+
async function clearDocument(sql, docId, namespace) {
|
|
18847
|
+
await sql`
|
|
18848
|
+
DELETE FROM rag_chunks
|
|
18849
|
+
WHERE namespace = ${namespace} AND doc_id = ${docId}
|
|
18850
|
+
`;
|
|
18851
|
+
}
|
|
18852
|
+
__name(clearDocument, "clearDocument");
|
|
18853
|
+
async function ingestDocument(sql, rows) {
|
|
18830
18854
|
if (rows.length === 0) return 0;
|
|
18831
|
-
|
|
18832
|
-
|
|
18833
|
-
|
|
18834
|
-
|
|
18835
|
-
|
|
18836
|
-
|
|
18837
|
-
|
|
18838
|
-
|
|
18839
|
-
|
|
18840
|
-
|
|
18841
|
-
|
|
18842
|
-
|
|
18843
|
-
|
|
18844
|
-
row.content,
|
|
18845
|
-
formatVector(row.embedding),
|
|
18846
|
-
JSON.stringify(row.metadata)
|
|
18847
|
-
]);
|
|
18848
|
-
await tx.unsafe(`INSERT INTO rag_chunks (doc_id, chunk_idx, namespace, content, embedding, metadata) VALUES ${placeholders}`, params);
|
|
18849
|
-
});
|
|
18855
|
+
const placeholders = rows.map((_, i) => {
|
|
18856
|
+
const base = i * 6;
|
|
18857
|
+
return `($${base + 1}, $${base + 2}, $${base + 3}, $${base + 4}, $${base + 5}::vector, $${base + 6}::jsonb)`;
|
|
18858
|
+
}).join(",");
|
|
18859
|
+
const params = rows.flatMap((row) => [
|
|
18860
|
+
row.docId,
|
|
18861
|
+
row.chunkIdx,
|
|
18862
|
+
row.namespace,
|
|
18863
|
+
row.content,
|
|
18864
|
+
formatVector(row.embedding),
|
|
18865
|
+
JSON.stringify(row.metadata)
|
|
18866
|
+
]);
|
|
18867
|
+
await sql.unsafe(`INSERT INTO rag_chunks (doc_id, chunk_idx, namespace, content, embedding, metadata) VALUES ${placeholders}`, params);
|
|
18850
18868
|
return rows.length;
|
|
18851
18869
|
}
|
|
18852
18870
|
__name(ingestDocument, "ingestDocument");
|
|
@@ -18916,8 +18934,6 @@ var CHUNK_INDEXES_DDL = `
|
|
|
18916
18934
|
|
|
18917
18935
|
// src/modules/rag/pipeline.ts
|
|
18918
18936
|
var DEFAULT_TOP_K = 5;
|
|
18919
|
-
var RAG_SCHEMA_MISSING_HINT = "run `stackbone db migrate add-rag` and `stackbone db migrate up`";
|
|
18920
|
-
var PG_UNDEFINED_TABLE = "42P01";
|
|
18921
18937
|
var RagPipeline = class {
|
|
18922
18938
|
static {
|
|
18923
18939
|
__name(this, "RagPipeline");
|
|
@@ -18982,19 +18998,16 @@ var RagPipeline = class {
|
|
|
18982
18998
|
if (started.error) return err(started.error);
|
|
18983
18999
|
jobId = started.data.jobId;
|
|
18984
19000
|
}
|
|
18985
|
-
|
|
18986
|
-
if (onProgress) await onProgress(event);
|
|
18987
|
-
}, "emit");
|
|
18988
|
-
const startEvent = {
|
|
19001
|
+
await onProgress?.({
|
|
18989
19002
|
type: "started",
|
|
18990
19003
|
jobId: jobId ?? request.id,
|
|
18991
19004
|
totalChunks
|
|
18992
|
-
};
|
|
18993
|
-
await emit(startEvent);
|
|
19005
|
+
});
|
|
18994
19006
|
try {
|
|
18995
19007
|
await ensureSchema(sql.data, dimensions);
|
|
18996
19008
|
const needsBatching = Boolean(writer || onProgress);
|
|
18997
19009
|
const batchSize = this._progressBatchSize ?? (needsBatching ? 1 : rows.length || 1);
|
|
19010
|
+
await clearDocument(sql.data, request.id, namespace);
|
|
18998
19011
|
let processed = 0;
|
|
18999
19012
|
for (let offset = 0; offset < rows.length; offset += batchSize) {
|
|
19000
19013
|
if (writer && jobId) {
|
|
@@ -19014,37 +19027,33 @@ var RagPipeline = class {
|
|
|
19014
19027
|
}
|
|
19015
19028
|
}
|
|
19016
19029
|
const slice = rows.slice(offset, offset + batchSize);
|
|
19017
|
-
await ingestDocument(sql.data,
|
|
19030
|
+
await ingestDocument(sql.data, slice);
|
|
19018
19031
|
processed += slice.length;
|
|
19019
|
-
const
|
|
19032
|
+
const currentDocument = {
|
|
19033
|
+
source: request.id,
|
|
19034
|
+
ordinal: processed - 1
|
|
19035
|
+
};
|
|
19036
|
+
await onProgress?.({
|
|
19020
19037
|
type: "progress",
|
|
19021
19038
|
jobId: jobId ?? request.id,
|
|
19022
19039
|
processedChunks: processed,
|
|
19023
19040
|
totalChunks,
|
|
19024
|
-
currentDocument
|
|
19025
|
-
|
|
19026
|
-
ordinal: processed - 1
|
|
19027
|
-
}
|
|
19028
|
-
};
|
|
19029
|
-
await emit(progressEvent);
|
|
19041
|
+
currentDocument
|
|
19042
|
+
});
|
|
19030
19043
|
if (writer && jobId) {
|
|
19031
19044
|
await writer.progress({
|
|
19032
19045
|
jobId,
|
|
19033
19046
|
processedChunks: processed,
|
|
19034
19047
|
totalChunks,
|
|
19035
|
-
currentDocument
|
|
19036
|
-
source: request.id,
|
|
19037
|
-
ordinal: processed - 1
|
|
19038
|
-
}
|
|
19048
|
+
currentDocument
|
|
19039
19049
|
});
|
|
19040
19050
|
}
|
|
19041
19051
|
}
|
|
19042
|
-
|
|
19052
|
+
await onProgress?.({
|
|
19043
19053
|
type: "completed",
|
|
19044
19054
|
jobId: jobId ?? request.id,
|
|
19045
19055
|
totalChunks
|
|
19046
|
-
};
|
|
19047
|
-
await emit(completedEvent);
|
|
19056
|
+
});
|
|
19048
19057
|
if (writer && jobId) await writer.complete({
|
|
19049
19058
|
jobId,
|
|
19050
19059
|
totalChunks
|
|
@@ -19055,12 +19064,11 @@ var RagPipeline = class {
|
|
|
19055
19064
|
});
|
|
19056
19065
|
} catch (cause) {
|
|
19057
19066
|
const mapped = toRagError(cause, "Ingest failed");
|
|
19058
|
-
|
|
19067
|
+
await onProgress?.({
|
|
19059
19068
|
type: "failed",
|
|
19060
19069
|
jobId: jobId ?? request.id,
|
|
19061
19070
|
error: mapped.message
|
|
19062
|
-
};
|
|
19063
|
-
await emit(failedEvent);
|
|
19071
|
+
});
|
|
19064
19072
|
if (writer && jobId) await writer.fail({
|
|
19065
19073
|
jobId,
|
|
19066
19074
|
error: mapped.message
|
|
@@ -19220,37 +19228,6 @@ function validateIngest(request, hasEmbedder) {
|
|
|
19220
19228
|
return ok(true);
|
|
19221
19229
|
}
|
|
19222
19230
|
__name(validateIngest, "validateIngest");
|
|
19223
|
-
function isTaggedError(cause) {
|
|
19224
|
-
return cause instanceof Error;
|
|
19225
|
-
}
|
|
19226
|
-
__name(isTaggedError, "isTaggedError");
|
|
19227
|
-
function toRagError(cause, message) {
|
|
19228
|
-
if (isTaggedError(cause) && cause.code === PG_UNDEFINED_TABLE) {
|
|
19229
|
-
return {
|
|
19230
|
-
code: "rag_schema_missing",
|
|
19231
|
-
message: `RAG tables are not installed \u2014 ${RAG_SCHEMA_MISSING_HINT}.`,
|
|
19232
|
-
cause,
|
|
19233
|
-
meta: {
|
|
19234
|
-
hint: RAG_SCHEMA_MISSING_HINT
|
|
19235
|
-
}
|
|
19236
|
-
};
|
|
19237
|
-
}
|
|
19238
|
-
if (isTaggedError(cause)) {
|
|
19239
|
-
const error48 = {
|
|
19240
|
-
code: cause.code ?? "rag_error",
|
|
19241
|
-
message: `${message}: ${cause.message}`,
|
|
19242
|
-
cause
|
|
19243
|
-
};
|
|
19244
|
-
if (cause.meta) error48.meta = cause.meta;
|
|
19245
|
-
return error48;
|
|
19246
|
-
}
|
|
19247
|
-
return {
|
|
19248
|
-
code: "rag_error",
|
|
19249
|
-
message,
|
|
19250
|
-
cause
|
|
19251
|
-
};
|
|
19252
|
-
}
|
|
19253
|
-
__name(toRagError, "toRagError");
|
|
19254
19231
|
|
|
19255
19232
|
// src/modules/rag/rag.ts
|
|
19256
19233
|
var DEFAULT_BATCH_SIZE4 = 128;
|
|
@@ -19262,10 +19239,14 @@ var RagModule = class {
|
|
|
19262
19239
|
_resolved;
|
|
19263
19240
|
_getAi;
|
|
19264
19241
|
_gate;
|
|
19265
|
-
|
|
19242
|
+
_testSqlOverride;
|
|
19243
|
+
_testJobWriterFactory;
|
|
19244
|
+
constructor(_resolved, _getAi, gate, testDeps) {
|
|
19266
19245
|
this._resolved = _resolved;
|
|
19267
19246
|
this._getAi = _getAi;
|
|
19268
19247
|
this._gate = gate ?? createModuleGate("rag", _resolved);
|
|
19248
|
+
if (testDeps?.sqlProvider) this._testSqlOverride = testDeps.sqlProvider;
|
|
19249
|
+
if (testDeps?.jobWriterFactory) this._testJobWriterFactory = testDeps.jobWriterFactory;
|
|
19269
19250
|
}
|
|
19270
19251
|
async ingest(request) {
|
|
19271
19252
|
const gateResult = await this._gate();
|
|
@@ -19298,7 +19279,8 @@ var RagModule = class {
|
|
|
19298
19279
|
if (gateResult.error) return err(gateResult.error);
|
|
19299
19280
|
const sql = this._testSqlOverride ? this._testSqlOverride() : this.sql();
|
|
19300
19281
|
if (sql.error) return err(sql.error);
|
|
19301
|
-
const
|
|
19282
|
+
const writerFactory = this._testJobWriterFactory ?? createSqlJobWriter;
|
|
19283
|
+
const writer = writerFactory(sql.data);
|
|
19302
19284
|
const channel = createProgressChannel();
|
|
19303
19285
|
const resolved = resolveIngestModel(request, this._resolved);
|
|
19304
19286
|
const requestWithHook = {
|
|
@@ -19329,7 +19311,7 @@ var RagModule = class {
|
|
|
19329
19311
|
return r;
|
|
19330
19312
|
}).catch((cause) => {
|
|
19331
19313
|
channel.close();
|
|
19332
|
-
return err(
|
|
19314
|
+
return err(toRagError(cause, "Ingest failed"));
|
|
19333
19315
|
});
|
|
19334
19316
|
return ok({
|
|
19335
19317
|
jobId,
|
|
@@ -19337,10 +19319,6 @@ var RagModule = class {
|
|
|
19337
19319
|
result
|
|
19338
19320
|
});
|
|
19339
19321
|
}
|
|
19340
|
-
/** Test-only seam — assigned by `ingest-async.spec.ts`. */
|
|
19341
|
-
_testJobWriter;
|
|
19342
|
-
/** Test-only seam — assigned by `ingest-async.spec.ts`. */
|
|
19343
|
-
_testSqlOverride;
|
|
19344
19322
|
async delete(ids, options) {
|
|
19345
19323
|
const gateResult = await this._gate();
|
|
19346
19324
|
if (gateResult.error) return err(gateResult.error);
|
|
@@ -19372,7 +19350,7 @@ var RagModule = class {
|
|
|
19372
19350
|
await reset(sql.data);
|
|
19373
19351
|
return ok(void 0);
|
|
19374
19352
|
} catch (cause) {
|
|
19375
|
-
return err(
|
|
19353
|
+
return err(toRagError(cause, "Reset failed"));
|
|
19376
19354
|
}
|
|
19377
19355
|
}
|
|
19378
19356
|
/**
|
|
@@ -19400,22 +19378,18 @@ var RagModule = class {
|
|
|
19400
19378
|
* `Result.err` with the same `database_not_configured` shape `client.database`
|
|
19401
19379
|
* raises, instead of throwing through the public surface.
|
|
19402
19380
|
*/
|
|
19403
|
-
// `_resolved` is reserved for future per-config overrides (e.g. routing
|
|
19404
|
-
// RAG queries through a logical replica). The URL itself is owned by the
|
|
19405
|
-
// shared handle.
|
|
19406
19381
|
sql() {
|
|
19407
|
-
void this._resolved;
|
|
19408
19382
|
try {
|
|
19409
19383
|
return ok(getDatabaseHandle().$client);
|
|
19410
19384
|
} catch (cause) {
|
|
19411
|
-
if (
|
|
19385
|
+
if (isTaggedError(cause) && cause.code === "database_not_configured") {
|
|
19412
19386
|
return err({
|
|
19413
19387
|
code: "database_not_configured",
|
|
19414
19388
|
message: cause.message,
|
|
19415
19389
|
cause
|
|
19416
19390
|
});
|
|
19417
19391
|
}
|
|
19418
|
-
return err(
|
|
19392
|
+
return err(toRagError(cause, "Database handle unavailable"));
|
|
19419
19393
|
}
|
|
19420
19394
|
}
|
|
19421
19395
|
async withPipeline(embedder, run) {
|
|
@@ -19536,27 +19510,6 @@ function resolveRetrieveModel(request, resolved) {
|
|
|
19536
19510
|
};
|
|
19537
19511
|
}
|
|
19538
19512
|
__name(resolveRetrieveModel, "resolveRetrieveModel");
|
|
19539
|
-
function isTaggedError2(cause) {
|
|
19540
|
-
return cause instanceof Error;
|
|
19541
|
-
}
|
|
19542
|
-
__name(isTaggedError2, "isTaggedError");
|
|
19543
|
-
function toRagError2(cause, message) {
|
|
19544
|
-
if (isTaggedError2(cause)) {
|
|
19545
|
-
const error48 = {
|
|
19546
|
-
code: cause.code ?? "rag_error",
|
|
19547
|
-
message: `${message}: ${cause.message}`,
|
|
19548
|
-
cause
|
|
19549
|
-
};
|
|
19550
|
-
if (cause.meta) error48.meta = cause.meta;
|
|
19551
|
-
return error48;
|
|
19552
|
-
}
|
|
19553
|
-
return {
|
|
19554
|
-
code: "rag_error",
|
|
19555
|
-
message,
|
|
19556
|
-
cause
|
|
19557
|
-
};
|
|
19558
|
-
}
|
|
19559
|
-
__name(toRagError2, "toRagError");
|
|
19560
19513
|
var DEFAULT_SIGNED_URL_TTL_SECONDS = 3600;
|
|
19561
19514
|
var StorageModule = class {
|
|
19562
19515
|
static {
|
|
@@ -19573,11 +19526,12 @@ var StorageModule = class {
|
|
|
19573
19526
|
return new StorageBucket(bucket, () => this.settings(), this._gate);
|
|
19574
19527
|
}
|
|
19575
19528
|
settings() {
|
|
19576
|
-
const accessKeyId = this._resolved.config.s3?.accessKeyId ?? this._resolved.env["
|
|
19577
|
-
const secretAccessKey = this._resolved.config.s3?.secretAccessKey ?? this._resolved.env["
|
|
19578
|
-
const endpoint = this._resolved.config.s3?.endpoint ?? this._resolved.env["
|
|
19579
|
-
const bucket = this._resolved.config.s3?.bucket ?? this._resolved.env["
|
|
19529
|
+
const accessKeyId = this._resolved.config.s3?.accessKeyId ?? this._resolved.env["STACKBONE_S3_ACCESS_KEY"];
|
|
19530
|
+
const secretAccessKey = this._resolved.config.s3?.secretAccessKey ?? this._resolved.env["STACKBONE_S3_SECRET_KEY"];
|
|
19531
|
+
const endpoint = this._resolved.config.s3?.endpoint ?? this._resolved.env["STACKBONE_S3_ENDPOINT"];
|
|
19532
|
+
const bucket = this._resolved.config.s3?.bucket ?? this._resolved.env["STACKBONE_S3_BUCKET"];
|
|
19580
19533
|
const agentId = this._resolved.config.agentId ?? this._resolved.env["STACKBONE_AGENT_ID"];
|
|
19534
|
+
const region = this._resolved.config.s3?.region ?? this._resolved.env["STACKBONE_S3_REGION"] ?? "auto";
|
|
19581
19535
|
if (!accessKeyId || !secretAccessKey || !endpoint) {
|
|
19582
19536
|
return err({
|
|
19583
19537
|
code: "s3_credentials_missing",
|
|
@@ -19598,7 +19552,7 @@ var StorageModule = class {
|
|
|
19598
19552
|
}
|
|
19599
19553
|
this._s3 ??= new S3Client({
|
|
19600
19554
|
endpoint,
|
|
19601
|
-
region
|
|
19555
|
+
region,
|
|
19602
19556
|
forcePathStyle: true,
|
|
19603
19557
|
credentials: {
|
|
19604
19558
|
accessKeyId,
|
|
@@ -19757,29 +19711,19 @@ var StorageBucket = class {
|
|
|
19757
19711
|
return ok(`${base}/${bucket}/${encodeS3Key(fullKey)}`);
|
|
19758
19712
|
}
|
|
19759
19713
|
async getSignedUploadUrl(key, options) {
|
|
19760
|
-
|
|
19761
|
-
|
|
19762
|
-
|
|
19763
|
-
|
|
19764
|
-
|
|
19765
|
-
const expiresIn = options?.expiresIn ?? DEFAULT_SIGNED_URL_TTL_SECONDS;
|
|
19766
|
-
try {
|
|
19767
|
-
const url2 = await getSignedUrl(client, new PutObjectCommand({
|
|
19768
|
-
Bucket: bucket,
|
|
19769
|
-
Key: fullKey,
|
|
19770
|
-
ContentType: options?.contentType
|
|
19771
|
-
}), {
|
|
19772
|
-
expiresIn
|
|
19773
|
-
});
|
|
19774
|
-
return ok({
|
|
19775
|
-
url: url2,
|
|
19776
|
-
expiresAt: new Date(Date.now() + expiresIn * 1e3)
|
|
19777
|
-
});
|
|
19778
|
-
} catch (cause) {
|
|
19779
|
-
return err(toStorageError("Signing upload URL failed", cause));
|
|
19780
|
-
}
|
|
19714
|
+
return this.signUrl(key, options, "Signing upload URL failed", ({ bucket, fullKey }) => new PutObjectCommand({
|
|
19715
|
+
Bucket: bucket,
|
|
19716
|
+
Key: fullKey,
|
|
19717
|
+
ContentType: options?.contentType
|
|
19718
|
+
}));
|
|
19781
19719
|
}
|
|
19782
19720
|
async getSignedDownloadUrl(key, options) {
|
|
19721
|
+
return this.signUrl(key, options, "Signing download URL failed", ({ bucket, fullKey }) => new GetObjectCommand({
|
|
19722
|
+
Bucket: bucket,
|
|
19723
|
+
Key: fullKey
|
|
19724
|
+
}));
|
|
19725
|
+
}
|
|
19726
|
+
async signUrl(key, options, failureMessage, buildCommand) {
|
|
19783
19727
|
const gateResult = await this.gate();
|
|
19784
19728
|
if (gateResult.error) return err(gateResult.error);
|
|
19785
19729
|
const resolved = this.resolve(key);
|
|
@@ -19787,9 +19731,9 @@ var StorageBucket = class {
|
|
|
19787
19731
|
const { client, bucket, fullKey } = resolved.data;
|
|
19788
19732
|
const expiresIn = options?.expiresIn ?? DEFAULT_SIGNED_URL_TTL_SECONDS;
|
|
19789
19733
|
try {
|
|
19790
|
-
const url2 = await getSignedUrl(client,
|
|
19791
|
-
|
|
19792
|
-
|
|
19734
|
+
const url2 = await getSignedUrl(client, buildCommand({
|
|
19735
|
+
bucket,
|
|
19736
|
+
fullKey
|
|
19793
19737
|
}), {
|
|
19794
19738
|
expiresIn
|
|
19795
19739
|
});
|
|
@@ -19798,7 +19742,7 @@ var StorageBucket = class {
|
|
|
19798
19742
|
expiresAt: new Date(Date.now() + expiresIn * 1e3)
|
|
19799
19743
|
});
|
|
19800
19744
|
} catch (cause) {
|
|
19801
|
-
return err(toStorageError(
|
|
19745
|
+
return err(toStorageError(failureMessage, cause));
|
|
19802
19746
|
}
|
|
19803
19747
|
}
|
|
19804
19748
|
/**
|
|
@@ -19824,8 +19768,8 @@ var StorageBucket = class {
|
|
|
19824
19768
|
});
|
|
19825
19769
|
}
|
|
19826
19770
|
};
|
|
19827
|
-
var S3_CREDENTIALS_MISSING_MESSAGE = "Cannot reach object storage \u2014 set `
|
|
19828
|
-
var S3_BUCKET_MISSING_MESSAGE = "No storage bucket configured \u2014 set `
|
|
19771
|
+
var S3_CREDENTIALS_MISSING_MESSAGE = "Cannot reach object storage \u2014 set `STACKBONE_S3_ACCESS_KEY`, `STACKBONE_S3_SECRET_KEY`, and `STACKBONE_S3_ENDPOINT` in the container or pass `s3` to `createClient({...})`.";
|
|
19772
|
+
var S3_BUCKET_MISSING_MESSAGE = "No storage bucket configured \u2014 set `STACKBONE_S3_BUCKET` in the container or pass `s3.bucket` to `createClient({...})`.";
|
|
19829
19773
|
var AGENT_ID_MISSING_MESSAGE = "No agent identity configured \u2014 set `STACKBONE_AGENT_ID` in the container or pass `agentId` to `createClient({...})`.";
|
|
19830
19774
|
function stripEtag(etag) {
|
|
19831
19775
|
return etag?.replace(/^"|"$/g, "");
|