@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.cjs
CHANGED
|
@@ -1793,9 +1793,9 @@ var nanoid = /^[a-zA-Z0-9_-]{21}$/;
|
|
|
1793
1793
|
var duration = /^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/;
|
|
1794
1794
|
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)?)??$/;
|
|
1795
1795
|
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})$/;
|
|
1796
|
-
var uuid = /* @__PURE__ */ __name((
|
|
1797
|
-
if (!
|
|
1798
|
-
return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${
|
|
1796
|
+
var uuid = /* @__PURE__ */ __name((version3) => {
|
|
1797
|
+
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)$/;
|
|
1798
|
+
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})$`);
|
|
1799
1799
|
}, "uuid");
|
|
1800
1800
|
var uuid4 = /* @__PURE__ */ uuid(4);
|
|
1801
1801
|
var uuid6 = /* @__PURE__ */ uuid(6);
|
|
@@ -14979,10 +14979,10 @@ function fromJSONSchema(schema, params) {
|
|
|
14979
14979
|
if (typeof schema === "boolean") {
|
|
14980
14980
|
return schema ? z.any() : z.never();
|
|
14981
14981
|
}
|
|
14982
|
-
const
|
|
14982
|
+
const version3 = detectVersion(schema, params?.defaultTarget);
|
|
14983
14983
|
const defs = schema.$defs || schema.definitions || {};
|
|
14984
14984
|
const ctx = {
|
|
14985
|
-
version:
|
|
14985
|
+
version: version3,
|
|
14986
14986
|
defs,
|
|
14987
14987
|
refs: /* @__PURE__ */ new Map(),
|
|
14988
14988
|
processing: /* @__PURE__ */ new Set(),
|
|
@@ -15560,6 +15560,13 @@ external_exports.object({
|
|
|
15560
15560
|
nextCursor: external_exports.string().nullable(),
|
|
15561
15561
|
prevCursor: external_exports.string().nullable()
|
|
15562
15562
|
});
|
|
15563
|
+
external_exports.object({
|
|
15564
|
+
fxtId: external_exports.uuid()
|
|
15565
|
+
});
|
|
15566
|
+
external_exports.object({
|
|
15567
|
+
input: jsonObject().nullable(),
|
|
15568
|
+
output: jsonObject().nullable()
|
|
15569
|
+
});
|
|
15563
15570
|
|
|
15564
15571
|
// ../validators/src/lib/auth/session.ts
|
|
15565
15572
|
var sessionUserSchema = external_exports.object({
|
|
@@ -16644,6 +16651,34 @@ function pickDefinedAsStrings(source) {
|
|
|
16644
16651
|
}
|
|
16645
16652
|
__name(pickDefinedAsStrings, "pickDefinedAsStrings");
|
|
16646
16653
|
|
|
16654
|
+
// src/lib/facade-helpers.ts
|
|
16655
|
+
function remapHttpNotFound(code, domainCode, message, meta3) {
|
|
16656
|
+
if (code !== "http_not_found") return null;
|
|
16657
|
+
const error48 = {
|
|
16658
|
+
code: domainCode,
|
|
16659
|
+
message
|
|
16660
|
+
};
|
|
16661
|
+
if (meta3) error48.meta = meta3;
|
|
16662
|
+
return err(error48);
|
|
16663
|
+
}
|
|
16664
|
+
__name(remapHttpNotFound, "remapHttpNotFound");
|
|
16665
|
+
function validateStringArray(values, field, errorCode) {
|
|
16666
|
+
if (!Array.isArray(values) || values.length === 0) {
|
|
16667
|
+
return err({
|
|
16668
|
+
code: errorCode,
|
|
16669
|
+
message: `\`${field}\` must be a non-empty array.`
|
|
16670
|
+
});
|
|
16671
|
+
}
|
|
16672
|
+
if (values.some((v) => typeof v !== "string" || !v.trim())) {
|
|
16673
|
+
return err({
|
|
16674
|
+
code: errorCode,
|
|
16675
|
+
message: `\`${field}[*]\` must be non-empty strings.`
|
|
16676
|
+
});
|
|
16677
|
+
}
|
|
16678
|
+
return null;
|
|
16679
|
+
}
|
|
16680
|
+
__name(validateStringArray, "validateStringArray");
|
|
16681
|
+
|
|
16647
16682
|
// src/facades/config/config.ts
|
|
16648
16683
|
var ConfigFacade = class {
|
|
16649
16684
|
static {
|
|
@@ -16665,7 +16700,11 @@ var ConfigFacade = class {
|
|
|
16665
16700
|
const gateResult = await this._gate();
|
|
16666
16701
|
if (gateResult.error) return err(gateResult.error);
|
|
16667
16702
|
const result = await this._http.get(`/api/config/${encodeURIComponent(key)}`);
|
|
16668
|
-
if (result.error)
|
|
16703
|
+
if (result.error) {
|
|
16704
|
+
return remapHttpNotFound(result.error.code, "config_not_found", `Config key \`${key}\` is not set for this agent.`, {
|
|
16705
|
+
key
|
|
16706
|
+
}) ?? result;
|
|
16707
|
+
}
|
|
16669
16708
|
return ok(result.data.value);
|
|
16670
16709
|
}
|
|
16671
16710
|
/**
|
|
@@ -16675,18 +16714,8 @@ var ConfigFacade = class {
|
|
|
16675
16714
|
* is `Partial<T>`).
|
|
16676
16715
|
*/
|
|
16677
16716
|
async getMany(keys) {
|
|
16678
|
-
|
|
16679
|
-
|
|
16680
|
-
code: "config_invalid_request",
|
|
16681
|
-
message: "`keys` must be a non-empty array."
|
|
16682
|
-
});
|
|
16683
|
-
}
|
|
16684
|
-
if (keys.some((k) => !k.trim())) {
|
|
16685
|
-
return err({
|
|
16686
|
-
code: "config_invalid_request",
|
|
16687
|
-
message: "`keys[*]` must be non-empty strings."
|
|
16688
|
-
});
|
|
16689
|
-
}
|
|
16717
|
+
const invalid = validateStringArray(keys, "keys", "config_invalid_request");
|
|
16718
|
+
if (invalid) return invalid;
|
|
16690
16719
|
const gateResult = await this._gate();
|
|
16691
16720
|
if (gateResult.error) return err(gateResult.error);
|
|
16692
16721
|
const result = await this._http.get("/api/config", {
|
|
@@ -16705,17 +16734,6 @@ var ConfigFacade = class {
|
|
|
16705
16734
|
return ok(values);
|
|
16706
16735
|
}
|
|
16707
16736
|
};
|
|
16708
|
-
function remapNotFound(code, key) {
|
|
16709
|
-
if (code !== "http_not_found") return null;
|
|
16710
|
-
return err({
|
|
16711
|
-
code: "config_not_found",
|
|
16712
|
-
message: `Config key \`${key}\` is not set for this agent.`,
|
|
16713
|
-
meta: {
|
|
16714
|
-
key
|
|
16715
|
-
}
|
|
16716
|
-
});
|
|
16717
|
-
}
|
|
16718
|
-
__name(remapNotFound, "remapNotFound");
|
|
16719
16737
|
|
|
16720
16738
|
// src/facades/connections/connections.ts
|
|
16721
16739
|
var ConnectionsFacade = class {
|
|
@@ -16801,7 +16819,11 @@ var SecretsFacade = class {
|
|
|
16801
16819
|
const gateResult = await this._gate();
|
|
16802
16820
|
if (gateResult.error) return err(gateResult.error);
|
|
16803
16821
|
const result = await this._http.get(`/api/secrets/${encodeURIComponent(name)}`);
|
|
16804
|
-
if (result.error)
|
|
16822
|
+
if (result.error) {
|
|
16823
|
+
return remapHttpNotFound(result.error.code, "secrets_not_found", `Secret \`${name}\` is not registered for this organization.`, {
|
|
16824
|
+
name
|
|
16825
|
+
}) ?? result;
|
|
16826
|
+
}
|
|
16805
16827
|
if (typeof result.data.value !== "string") {
|
|
16806
16828
|
return err({
|
|
16807
16829
|
code: "secrets_invalid_response",
|
|
@@ -16814,23 +16836,13 @@ var SecretsFacade = class {
|
|
|
16814
16836
|
return ok(result.data.value);
|
|
16815
16837
|
}
|
|
16816
16838
|
/**
|
|
16817
|
-
* Names absent from the
|
|
16839
|
+
* Names absent from the organization come back as omissions in the response —
|
|
16818
16840
|
* the returned map only contains entries the control plane actually has.
|
|
16819
16841
|
* Callers that need "all-or-nothing" semantics should diff the keys.
|
|
16820
16842
|
*/
|
|
16821
16843
|
async getMany(names) {
|
|
16822
|
-
|
|
16823
|
-
|
|
16824
|
-
code: "secrets_invalid_request",
|
|
16825
|
-
message: "`names` must be a non-empty array."
|
|
16826
|
-
});
|
|
16827
|
-
}
|
|
16828
|
-
if (names.some((n) => !n.trim())) {
|
|
16829
|
-
return err({
|
|
16830
|
-
code: "secrets_invalid_request",
|
|
16831
|
-
message: "`names[*]` must be non-empty strings."
|
|
16832
|
-
});
|
|
16833
|
-
}
|
|
16844
|
+
const invalid = validateStringArray(names, "names", "secrets_invalid_request");
|
|
16845
|
+
if (invalid) return invalid;
|
|
16834
16846
|
const gateResult = await this._gate();
|
|
16835
16847
|
if (gateResult.error) return err(gateResult.error);
|
|
16836
16848
|
const result = await this._http.get("/api/secrets", {
|
|
@@ -16849,17 +16861,6 @@ var SecretsFacade = class {
|
|
|
16849
16861
|
return ok(values);
|
|
16850
16862
|
}
|
|
16851
16863
|
};
|
|
16852
|
-
function remapNotFound2(code, name) {
|
|
16853
|
-
if (code !== "http_not_found") return null;
|
|
16854
|
-
return err({
|
|
16855
|
-
code: "secrets_not_found",
|
|
16856
|
-
message: `Secret \`${name}\` is not registered for this workspace.`,
|
|
16857
|
-
meta: {
|
|
16858
|
-
name
|
|
16859
|
-
}
|
|
16860
|
-
});
|
|
16861
|
-
}
|
|
16862
|
-
__name(remapNotFound2, "remapNotFound");
|
|
16863
16864
|
|
|
16864
16865
|
// src/lib/http-client.ts
|
|
16865
16866
|
var RETRYABLE_STATUS = /* @__PURE__ */ new Set([
|
|
@@ -17742,6 +17743,11 @@ async function aggregateRunCost(runId, options) {
|
|
|
17742
17743
|
};
|
|
17743
17744
|
}
|
|
17744
17745
|
__name(aggregateRunCost, "aggregateRunCost");
|
|
17746
|
+
|
|
17747
|
+
// package.json
|
|
17748
|
+
var version2 = "0.1.0-alpha.2";
|
|
17749
|
+
|
|
17750
|
+
// src/observability/logger.ts
|
|
17745
17751
|
var LOG_LEVELS = {
|
|
17746
17752
|
trace: 10,
|
|
17747
17753
|
debug: 20,
|
|
@@ -17955,7 +17961,7 @@ var OtlpHttpDestination = class OtlpHttpDestination2 {
|
|
|
17955
17961
|
};
|
|
17956
17962
|
var SDK_SCOPE = {
|
|
17957
17963
|
name: "@stackbone/sdk",
|
|
17958
|
-
version:
|
|
17964
|
+
version: version2
|
|
17959
17965
|
};
|
|
17960
17966
|
function buildOtlpLogsBody(records, resourceAttributes) {
|
|
17961
17967
|
return {
|
|
@@ -17988,11 +17994,12 @@ function toOtlpLogRecord(record2) {
|
|
|
17988
17994
|
};
|
|
17989
17995
|
}
|
|
17990
17996
|
__name(toOtlpLogRecord, "toOtlpLogRecord");
|
|
17997
|
+
var SEVERITY_TEXT_BY_LEVEL = Object.fromEntries(Object.entries(LOG_LEVELS).map(([name, value]) => [
|
|
17998
|
+
value,
|
|
17999
|
+
name.toUpperCase()
|
|
18000
|
+
]));
|
|
17991
18001
|
function severityText(level) {
|
|
17992
|
-
|
|
17993
|
-
if (value === level) return name.toUpperCase();
|
|
17994
|
-
}
|
|
17995
|
-
return "INFO";
|
|
18002
|
+
return SEVERITY_TEXT_BY_LEVEL[level] ?? "INFO";
|
|
17996
18003
|
}
|
|
17997
18004
|
__name(severityText, "severityText");
|
|
17998
18005
|
function toOtlpAttributes(attrs) {
|
|
@@ -18120,7 +18127,7 @@ var RunStepsSpanProcessor = class {
|
|
|
18120
18127
|
this.intervalMs = options.flushIntervalMs ?? DEFAULT_INTERVAL_MS2;
|
|
18121
18128
|
this.resolveStepType = options.resolveStepType ?? defaultStepTypeResolver;
|
|
18122
18129
|
this.newId = options.newId ?? crypto$1.randomUUID;
|
|
18123
|
-
this.connectionString = options.connectionString ?? process.env["
|
|
18130
|
+
this.connectionString = options.connectionString ?? process.env["STACKBONE_POSTGRES_URL"];
|
|
18124
18131
|
if (options.sql) {
|
|
18125
18132
|
this.sql = options.sql;
|
|
18126
18133
|
this.ownsSql = false;
|
|
@@ -18160,11 +18167,11 @@ var RunStepsSpanProcessor = class {
|
|
|
18160
18167
|
}
|
|
18161
18168
|
}
|
|
18162
18169
|
buildRow(span) {
|
|
18163
|
-
const runId = readString(span.attributes[RUN_ID_ATTRIBUTE]);
|
|
18164
|
-
if (!runId) return null;
|
|
18165
18170
|
const spanId = span.spanContext().spanId;
|
|
18166
18171
|
const stepId = this.stepIdBySpanId.get(spanId) ?? this.newId();
|
|
18167
18172
|
this.stepIdBySpanId.delete(spanId);
|
|
18173
|
+
const runId = readString(span.attributes[RUN_ID_ATTRIBUTE]);
|
|
18174
|
+
if (!runId) return null;
|
|
18168
18175
|
const parentSpanId = span.parentSpanContext?.spanId ?? span.parentSpanId ?? null;
|
|
18169
18176
|
const parentStepId = parentSpanId ? this.stepIdBySpanId.get(parentSpanId) ?? null : null;
|
|
18170
18177
|
const startedAt = formatHrTime(span.startTime);
|
|
@@ -18304,7 +18311,7 @@ var ObservabilityModule = class {
|
|
|
18304
18311
|
if (!this._processor) {
|
|
18305
18312
|
const merged = {
|
|
18306
18313
|
...options,
|
|
18307
|
-
connectionString: options.connectionString ?? this._resolved.config.databaseUrl ?? this._resolved.env["
|
|
18314
|
+
connectionString: options.connectionString ?? this._resolved.config.databaseUrl ?? this._resolved.env["STACKBONE_POSTGRES_URL"]
|
|
18308
18315
|
};
|
|
18309
18316
|
this._processor = new RunStepsSpanProcessor(merged);
|
|
18310
18317
|
}
|
|
@@ -18363,7 +18370,7 @@ var ObservabilityModule = class {
|
|
|
18363
18370
|
if (!sql) {
|
|
18364
18371
|
return err({
|
|
18365
18372
|
code: "database_url_missing",
|
|
18366
|
-
message: "Cannot reach the agent Postgres \u2014 set `
|
|
18373
|
+
message: "Cannot reach the agent Postgres \u2014 set `STACKBONE_POSTGRES_URL` in the container or pass `databaseUrl` to `createClient({...})`."
|
|
18367
18374
|
});
|
|
18368
18375
|
}
|
|
18369
18376
|
try {
|
|
@@ -18384,7 +18391,7 @@ var ObservabilityModule = class {
|
|
|
18384
18391
|
// don't pay the dep cost.
|
|
18385
18392
|
async resolveSql() {
|
|
18386
18393
|
if (this._sqlResolved) return this._sql;
|
|
18387
|
-
const connectionString = this._resolved.config.databaseUrl ?? this._resolved.env["
|
|
18394
|
+
const connectionString = this._resolved.config.databaseUrl ?? this._resolved.env["STACKBONE_POSTGRES_URL"];
|
|
18388
18395
|
if (!connectionString) {
|
|
18389
18396
|
this._sqlResolved = true;
|
|
18390
18397
|
return null;
|
|
@@ -18614,6 +18621,41 @@ function isUnsupportedModelError(error48) {
|
|
|
18614
18621
|
}
|
|
18615
18622
|
__name(isUnsupportedModelError, "isUnsupportedModelError");
|
|
18616
18623
|
|
|
18624
|
+
// src/modules/rag/errors.ts
|
|
18625
|
+
var PG_UNDEFINED_TABLE = "42P01";
|
|
18626
|
+
var RAG_SCHEMA_MISSING_HINT = "run `stackbone db migrate add-rag` and `stackbone db migrate up`";
|
|
18627
|
+
function isTaggedError(cause) {
|
|
18628
|
+
return cause instanceof Error;
|
|
18629
|
+
}
|
|
18630
|
+
__name(isTaggedError, "isTaggedError");
|
|
18631
|
+
function toRagError(cause, message, fallbackCode = "rag_error") {
|
|
18632
|
+
if (isTaggedError(cause) && cause.code === PG_UNDEFINED_TABLE) {
|
|
18633
|
+
return {
|
|
18634
|
+
code: "rag_schema_missing",
|
|
18635
|
+
message: `RAG tables are not installed \u2014 ${RAG_SCHEMA_MISSING_HINT}.`,
|
|
18636
|
+
cause,
|
|
18637
|
+
meta: {
|
|
18638
|
+
hint: RAG_SCHEMA_MISSING_HINT
|
|
18639
|
+
}
|
|
18640
|
+
};
|
|
18641
|
+
}
|
|
18642
|
+
if (isTaggedError(cause)) {
|
|
18643
|
+
const error48 = {
|
|
18644
|
+
code: cause.code ?? fallbackCode,
|
|
18645
|
+
message: `${message}: ${cause.message}`,
|
|
18646
|
+
cause
|
|
18647
|
+
};
|
|
18648
|
+
if (cause.meta) error48.meta = cause.meta;
|
|
18649
|
+
return error48;
|
|
18650
|
+
}
|
|
18651
|
+
return {
|
|
18652
|
+
code: fallbackCode,
|
|
18653
|
+
message,
|
|
18654
|
+
cause
|
|
18655
|
+
};
|
|
18656
|
+
}
|
|
18657
|
+
__name(toRagError, "toRagError");
|
|
18658
|
+
|
|
18617
18659
|
// src/modules/rag/jobs.ts
|
|
18618
18660
|
function createSqlJobWriter(sql) {
|
|
18619
18661
|
return {
|
|
@@ -18639,7 +18681,7 @@ function createSqlJobWriter(sql) {
|
|
|
18639
18681
|
jobId: row.id
|
|
18640
18682
|
});
|
|
18641
18683
|
} catch (cause) {
|
|
18642
|
-
return err(
|
|
18684
|
+
return err(toRagError(cause, "Job start failed", "rag_jobs_error"));
|
|
18643
18685
|
}
|
|
18644
18686
|
},
|
|
18645
18687
|
async progress({ jobId, processedChunks, totalChunks, currentDocument }) {
|
|
@@ -18678,7 +18720,7 @@ function createSqlJobWriter(sql) {
|
|
|
18678
18720
|
},
|
|
18679
18721
|
async isCancelled({ jobId }) {
|
|
18680
18722
|
const rows = await sql`
|
|
18681
|
-
SELECT
|
|
18723
|
+
SELECT status FROM stackbone_rag_jobs WHERE id = ${jobId} LIMIT 1
|
|
18682
18724
|
`;
|
|
18683
18725
|
return rows[0]?.status === "cancelled";
|
|
18684
18726
|
}
|
|
@@ -18686,10 +18728,6 @@ function createSqlJobWriter(sql) {
|
|
|
18686
18728
|
}
|
|
18687
18729
|
__name(createSqlJobWriter, "createSqlJobWriter");
|
|
18688
18730
|
async function ensureCollection(sql, name) {
|
|
18689
|
-
const existing = await sql`
|
|
18690
|
-
SELECT id FROM stackbone_rag_collections WHERE name = ${name} LIMIT 1
|
|
18691
|
-
`;
|
|
18692
|
-
if (existing[0]) return existing[0].id;
|
|
18693
18731
|
const inserted = await sql`
|
|
18694
18732
|
INSERT INTO stackbone_rag_collections (name) VALUES (${name})
|
|
18695
18733
|
ON CONFLICT (name) DO UPDATE SET name = EXCLUDED.name
|
|
@@ -18697,37 +18735,11 @@ async function ensureCollection(sql, name) {
|
|
|
18697
18735
|
`;
|
|
18698
18736
|
const row = inserted[0];
|
|
18699
18737
|
if (!row) {
|
|
18700
|
-
throw new Error(`stackbone_rag_collections
|
|
18738
|
+
throw new Error(`stackbone_rag_collections upsert returned no row for ${name}`);
|
|
18701
18739
|
}
|
|
18702
18740
|
return row.id;
|
|
18703
18741
|
}
|
|
18704
18742
|
__name(ensureCollection, "ensureCollection");
|
|
18705
|
-
function toJobsError(cause, message) {
|
|
18706
|
-
if (cause instanceof Error) {
|
|
18707
|
-
const tagged = cause;
|
|
18708
|
-
if (tagged.code === "42P01") {
|
|
18709
|
-
return {
|
|
18710
|
-
code: "rag_schema_missing",
|
|
18711
|
-
message: "RAG tables are not installed \u2014 run `stackbone db migrate add-rag` and `stackbone db migrate up`.",
|
|
18712
|
-
cause,
|
|
18713
|
-
meta: {
|
|
18714
|
-
hint: "run `stackbone db migrate add-rag` and `stackbone db migrate up`"
|
|
18715
|
-
}
|
|
18716
|
-
};
|
|
18717
|
-
}
|
|
18718
|
-
return {
|
|
18719
|
-
code: tagged.code ?? "rag_jobs_error",
|
|
18720
|
-
message: `${message}: ${cause.message}`,
|
|
18721
|
-
cause
|
|
18722
|
-
};
|
|
18723
|
-
}
|
|
18724
|
-
return {
|
|
18725
|
-
code: "rag_jobs_error",
|
|
18726
|
-
message,
|
|
18727
|
-
cause
|
|
18728
|
-
};
|
|
18729
|
-
}
|
|
18730
|
-
__name(toJobsError, "toJobsError");
|
|
18731
18743
|
var PDF_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
18732
18744
|
"application/pdf",
|
|
18733
18745
|
"application/x-pdf"
|
|
@@ -18787,10 +18799,12 @@ __name(looksLikePdf, "looksLikePdf");
|
|
|
18787
18799
|
var DEFAULT_NAMESPACE = "default";
|
|
18788
18800
|
var META_KEY_DIMENSIONS = "dimensions";
|
|
18789
18801
|
var META_KEY_DISTANCE = "distance";
|
|
18802
|
+
var schemaVerifiedDimensions = /* @__PURE__ */ new WeakMap();
|
|
18790
18803
|
async function ensureSchema(sql, dimensions) {
|
|
18791
18804
|
if (!Number.isInteger(dimensions) || dimensions <= 0 || dimensions > 8192) {
|
|
18792
18805
|
throw new Error(`rag.ensureSchema: invalid dimensions ${dimensions}. Must be a positive integer <= 8192.`);
|
|
18793
18806
|
}
|
|
18807
|
+
if (schemaVerifiedDimensions.get(sql) === dimensions) return;
|
|
18794
18808
|
const existing = await sql`
|
|
18795
18809
|
SELECT value::int AS value FROM _rag_meta WHERE key = ${META_KEY_DIMENSIONS}
|
|
18796
18810
|
`.catch(() => []);
|
|
@@ -18805,6 +18819,7 @@ async function ensureSchema(sql, dimensions) {
|
|
|
18805
18819
|
};
|
|
18806
18820
|
throw error48;
|
|
18807
18821
|
}
|
|
18822
|
+
schemaVerifiedDimensions.set(sql, dimensions);
|
|
18808
18823
|
return;
|
|
18809
18824
|
}
|
|
18810
18825
|
await sql.begin(async (tx) => {
|
|
@@ -18824,6 +18839,7 @@ async function ensureSchema(sql, dimensions) {
|
|
|
18824
18839
|
ON CONFLICT (key) DO NOTHING
|
|
18825
18840
|
`;
|
|
18826
18841
|
});
|
|
18842
|
+
schemaVerifiedDimensions.set(sql, dimensions);
|
|
18827
18843
|
}
|
|
18828
18844
|
__name(ensureSchema, "ensureSchema");
|
|
18829
18845
|
async function reset(sql) {
|
|
@@ -18831,29 +18847,31 @@ async function reset(sql) {
|
|
|
18831
18847
|
await tx`DROP TABLE IF EXISTS rag_chunks`;
|
|
18832
18848
|
await tx`DROP TABLE IF EXISTS _rag_meta`;
|
|
18833
18849
|
});
|
|
18850
|
+
schemaVerifiedDimensions.delete(sql);
|
|
18834
18851
|
}
|
|
18835
18852
|
__name(reset, "reset");
|
|
18836
|
-
async function
|
|
18853
|
+
async function clearDocument(sql, docId, namespace) {
|
|
18854
|
+
await sql`
|
|
18855
|
+
DELETE FROM rag_chunks
|
|
18856
|
+
WHERE namespace = ${namespace} AND doc_id = ${docId}
|
|
18857
|
+
`;
|
|
18858
|
+
}
|
|
18859
|
+
__name(clearDocument, "clearDocument");
|
|
18860
|
+
async function ingestDocument(sql, rows) {
|
|
18837
18861
|
if (rows.length === 0) return 0;
|
|
18838
|
-
|
|
18839
|
-
|
|
18840
|
-
|
|
18841
|
-
|
|
18842
|
-
|
|
18843
|
-
|
|
18844
|
-
|
|
18845
|
-
|
|
18846
|
-
|
|
18847
|
-
|
|
18848
|
-
|
|
18849
|
-
|
|
18850
|
-
|
|
18851
|
-
row.content,
|
|
18852
|
-
formatVector(row.embedding),
|
|
18853
|
-
JSON.stringify(row.metadata)
|
|
18854
|
-
]);
|
|
18855
|
-
await tx.unsafe(`INSERT INTO rag_chunks (doc_id, chunk_idx, namespace, content, embedding, metadata) VALUES ${placeholders}`, params);
|
|
18856
|
-
});
|
|
18862
|
+
const placeholders = rows.map((_, i) => {
|
|
18863
|
+
const base = i * 6;
|
|
18864
|
+
return `($${base + 1}, $${base + 2}, $${base + 3}, $${base + 4}, $${base + 5}::vector, $${base + 6}::jsonb)`;
|
|
18865
|
+
}).join(",");
|
|
18866
|
+
const params = rows.flatMap((row) => [
|
|
18867
|
+
row.docId,
|
|
18868
|
+
row.chunkIdx,
|
|
18869
|
+
row.namespace,
|
|
18870
|
+
row.content,
|
|
18871
|
+
formatVector(row.embedding),
|
|
18872
|
+
JSON.stringify(row.metadata)
|
|
18873
|
+
]);
|
|
18874
|
+
await sql.unsafe(`INSERT INTO rag_chunks (doc_id, chunk_idx, namespace, content, embedding, metadata) VALUES ${placeholders}`, params);
|
|
18857
18875
|
return rows.length;
|
|
18858
18876
|
}
|
|
18859
18877
|
__name(ingestDocument, "ingestDocument");
|
|
@@ -18923,8 +18941,6 @@ var CHUNK_INDEXES_DDL = `
|
|
|
18923
18941
|
|
|
18924
18942
|
// src/modules/rag/pipeline.ts
|
|
18925
18943
|
var DEFAULT_TOP_K = 5;
|
|
18926
|
-
var RAG_SCHEMA_MISSING_HINT = "run `stackbone db migrate add-rag` and `stackbone db migrate up`";
|
|
18927
|
-
var PG_UNDEFINED_TABLE = "42P01";
|
|
18928
18944
|
var RagPipeline = class {
|
|
18929
18945
|
static {
|
|
18930
18946
|
__name(this, "RagPipeline");
|
|
@@ -18989,19 +19005,16 @@ var RagPipeline = class {
|
|
|
18989
19005
|
if (started.error) return err(started.error);
|
|
18990
19006
|
jobId = started.data.jobId;
|
|
18991
19007
|
}
|
|
18992
|
-
|
|
18993
|
-
if (onProgress) await onProgress(event);
|
|
18994
|
-
}, "emit");
|
|
18995
|
-
const startEvent = {
|
|
19008
|
+
await onProgress?.({
|
|
18996
19009
|
type: "started",
|
|
18997
19010
|
jobId: jobId ?? request.id,
|
|
18998
19011
|
totalChunks
|
|
18999
|
-
};
|
|
19000
|
-
await emit(startEvent);
|
|
19012
|
+
});
|
|
19001
19013
|
try {
|
|
19002
19014
|
await ensureSchema(sql.data, dimensions);
|
|
19003
19015
|
const needsBatching = Boolean(writer || onProgress);
|
|
19004
19016
|
const batchSize = this._progressBatchSize ?? (needsBatching ? 1 : rows.length || 1);
|
|
19017
|
+
await clearDocument(sql.data, request.id, namespace);
|
|
19005
19018
|
let processed = 0;
|
|
19006
19019
|
for (let offset = 0; offset < rows.length; offset += batchSize) {
|
|
19007
19020
|
if (writer && jobId) {
|
|
@@ -19021,37 +19034,33 @@ var RagPipeline = class {
|
|
|
19021
19034
|
}
|
|
19022
19035
|
}
|
|
19023
19036
|
const slice = rows.slice(offset, offset + batchSize);
|
|
19024
|
-
await ingestDocument(sql.data,
|
|
19037
|
+
await ingestDocument(sql.data, slice);
|
|
19025
19038
|
processed += slice.length;
|
|
19026
|
-
const
|
|
19039
|
+
const currentDocument = {
|
|
19040
|
+
source: request.id,
|
|
19041
|
+
ordinal: processed - 1
|
|
19042
|
+
};
|
|
19043
|
+
await onProgress?.({
|
|
19027
19044
|
type: "progress",
|
|
19028
19045
|
jobId: jobId ?? request.id,
|
|
19029
19046
|
processedChunks: processed,
|
|
19030
19047
|
totalChunks,
|
|
19031
|
-
currentDocument
|
|
19032
|
-
|
|
19033
|
-
ordinal: processed - 1
|
|
19034
|
-
}
|
|
19035
|
-
};
|
|
19036
|
-
await emit(progressEvent);
|
|
19048
|
+
currentDocument
|
|
19049
|
+
});
|
|
19037
19050
|
if (writer && jobId) {
|
|
19038
19051
|
await writer.progress({
|
|
19039
19052
|
jobId,
|
|
19040
19053
|
processedChunks: processed,
|
|
19041
19054
|
totalChunks,
|
|
19042
|
-
currentDocument
|
|
19043
|
-
source: request.id,
|
|
19044
|
-
ordinal: processed - 1
|
|
19045
|
-
}
|
|
19055
|
+
currentDocument
|
|
19046
19056
|
});
|
|
19047
19057
|
}
|
|
19048
19058
|
}
|
|
19049
|
-
|
|
19059
|
+
await onProgress?.({
|
|
19050
19060
|
type: "completed",
|
|
19051
19061
|
jobId: jobId ?? request.id,
|
|
19052
19062
|
totalChunks
|
|
19053
|
-
};
|
|
19054
|
-
await emit(completedEvent);
|
|
19063
|
+
});
|
|
19055
19064
|
if (writer && jobId) await writer.complete({
|
|
19056
19065
|
jobId,
|
|
19057
19066
|
totalChunks
|
|
@@ -19062,12 +19071,11 @@ var RagPipeline = class {
|
|
|
19062
19071
|
});
|
|
19063
19072
|
} catch (cause) {
|
|
19064
19073
|
const mapped = toRagError(cause, "Ingest failed");
|
|
19065
|
-
|
|
19074
|
+
await onProgress?.({
|
|
19066
19075
|
type: "failed",
|
|
19067
19076
|
jobId: jobId ?? request.id,
|
|
19068
19077
|
error: mapped.message
|
|
19069
|
-
};
|
|
19070
|
-
await emit(failedEvent);
|
|
19078
|
+
});
|
|
19071
19079
|
if (writer && jobId) await writer.fail({
|
|
19072
19080
|
jobId,
|
|
19073
19081
|
error: mapped.message
|
|
@@ -19227,37 +19235,6 @@ function validateIngest(request, hasEmbedder) {
|
|
|
19227
19235
|
return ok(true);
|
|
19228
19236
|
}
|
|
19229
19237
|
__name(validateIngest, "validateIngest");
|
|
19230
|
-
function isTaggedError(cause) {
|
|
19231
|
-
return cause instanceof Error;
|
|
19232
|
-
}
|
|
19233
|
-
__name(isTaggedError, "isTaggedError");
|
|
19234
|
-
function toRagError(cause, message) {
|
|
19235
|
-
if (isTaggedError(cause) && cause.code === PG_UNDEFINED_TABLE) {
|
|
19236
|
-
return {
|
|
19237
|
-
code: "rag_schema_missing",
|
|
19238
|
-
message: `RAG tables are not installed \u2014 ${RAG_SCHEMA_MISSING_HINT}.`,
|
|
19239
|
-
cause,
|
|
19240
|
-
meta: {
|
|
19241
|
-
hint: RAG_SCHEMA_MISSING_HINT
|
|
19242
|
-
}
|
|
19243
|
-
};
|
|
19244
|
-
}
|
|
19245
|
-
if (isTaggedError(cause)) {
|
|
19246
|
-
const error48 = {
|
|
19247
|
-
code: cause.code ?? "rag_error",
|
|
19248
|
-
message: `${message}: ${cause.message}`,
|
|
19249
|
-
cause
|
|
19250
|
-
};
|
|
19251
|
-
if (cause.meta) error48.meta = cause.meta;
|
|
19252
|
-
return error48;
|
|
19253
|
-
}
|
|
19254
|
-
return {
|
|
19255
|
-
code: "rag_error",
|
|
19256
|
-
message,
|
|
19257
|
-
cause
|
|
19258
|
-
};
|
|
19259
|
-
}
|
|
19260
|
-
__name(toRagError, "toRagError");
|
|
19261
19238
|
|
|
19262
19239
|
// src/modules/rag/rag.ts
|
|
19263
19240
|
var DEFAULT_BATCH_SIZE4 = 128;
|
|
@@ -19269,10 +19246,14 @@ var RagModule = class {
|
|
|
19269
19246
|
_resolved;
|
|
19270
19247
|
_getAi;
|
|
19271
19248
|
_gate;
|
|
19272
|
-
|
|
19249
|
+
_testSqlOverride;
|
|
19250
|
+
_testJobWriterFactory;
|
|
19251
|
+
constructor(_resolved, _getAi, gate, testDeps) {
|
|
19273
19252
|
this._resolved = _resolved;
|
|
19274
19253
|
this._getAi = _getAi;
|
|
19275
19254
|
this._gate = gate ?? createModuleGate("rag", _resolved);
|
|
19255
|
+
if (testDeps?.sqlProvider) this._testSqlOverride = testDeps.sqlProvider;
|
|
19256
|
+
if (testDeps?.jobWriterFactory) this._testJobWriterFactory = testDeps.jobWriterFactory;
|
|
19276
19257
|
}
|
|
19277
19258
|
async ingest(request) {
|
|
19278
19259
|
const gateResult = await this._gate();
|
|
@@ -19305,7 +19286,8 @@ var RagModule = class {
|
|
|
19305
19286
|
if (gateResult.error) return err(gateResult.error);
|
|
19306
19287
|
const sql = this._testSqlOverride ? this._testSqlOverride() : this.sql();
|
|
19307
19288
|
if (sql.error) return err(sql.error);
|
|
19308
|
-
const
|
|
19289
|
+
const writerFactory = this._testJobWriterFactory ?? createSqlJobWriter;
|
|
19290
|
+
const writer = writerFactory(sql.data);
|
|
19309
19291
|
const channel = createProgressChannel();
|
|
19310
19292
|
const resolved = resolveIngestModel(request, this._resolved);
|
|
19311
19293
|
const requestWithHook = {
|
|
@@ -19336,7 +19318,7 @@ var RagModule = class {
|
|
|
19336
19318
|
return r;
|
|
19337
19319
|
}).catch((cause) => {
|
|
19338
19320
|
channel.close();
|
|
19339
|
-
return err(
|
|
19321
|
+
return err(toRagError(cause, "Ingest failed"));
|
|
19340
19322
|
});
|
|
19341
19323
|
return ok({
|
|
19342
19324
|
jobId,
|
|
@@ -19344,10 +19326,6 @@ var RagModule = class {
|
|
|
19344
19326
|
result
|
|
19345
19327
|
});
|
|
19346
19328
|
}
|
|
19347
|
-
/** Test-only seam — assigned by `ingest-async.spec.ts`. */
|
|
19348
|
-
_testJobWriter;
|
|
19349
|
-
/** Test-only seam — assigned by `ingest-async.spec.ts`. */
|
|
19350
|
-
_testSqlOverride;
|
|
19351
19329
|
async delete(ids, options) {
|
|
19352
19330
|
const gateResult = await this._gate();
|
|
19353
19331
|
if (gateResult.error) return err(gateResult.error);
|
|
@@ -19379,7 +19357,7 @@ var RagModule = class {
|
|
|
19379
19357
|
await reset(sql.data);
|
|
19380
19358
|
return ok(void 0);
|
|
19381
19359
|
} catch (cause) {
|
|
19382
|
-
return err(
|
|
19360
|
+
return err(toRagError(cause, "Reset failed"));
|
|
19383
19361
|
}
|
|
19384
19362
|
}
|
|
19385
19363
|
/**
|
|
@@ -19407,22 +19385,18 @@ var RagModule = class {
|
|
|
19407
19385
|
* `Result.err` with the same `database_not_configured` shape `client.database`
|
|
19408
19386
|
* raises, instead of throwing through the public surface.
|
|
19409
19387
|
*/
|
|
19410
|
-
// `_resolved` is reserved for future per-config overrides (e.g. routing
|
|
19411
|
-
// RAG queries through a logical replica). The URL itself is owned by the
|
|
19412
|
-
// shared handle.
|
|
19413
19388
|
sql() {
|
|
19414
|
-
void this._resolved;
|
|
19415
19389
|
try {
|
|
19416
19390
|
return ok(getDatabaseHandle().$client);
|
|
19417
19391
|
} catch (cause) {
|
|
19418
|
-
if (
|
|
19392
|
+
if (isTaggedError(cause) && cause.code === "database_not_configured") {
|
|
19419
19393
|
return err({
|
|
19420
19394
|
code: "database_not_configured",
|
|
19421
19395
|
message: cause.message,
|
|
19422
19396
|
cause
|
|
19423
19397
|
});
|
|
19424
19398
|
}
|
|
19425
|
-
return err(
|
|
19399
|
+
return err(toRagError(cause, "Database handle unavailable"));
|
|
19426
19400
|
}
|
|
19427
19401
|
}
|
|
19428
19402
|
async withPipeline(embedder, run) {
|
|
@@ -19543,27 +19517,6 @@ function resolveRetrieveModel(request, resolved) {
|
|
|
19543
19517
|
};
|
|
19544
19518
|
}
|
|
19545
19519
|
__name(resolveRetrieveModel, "resolveRetrieveModel");
|
|
19546
|
-
function isTaggedError2(cause) {
|
|
19547
|
-
return cause instanceof Error;
|
|
19548
|
-
}
|
|
19549
|
-
__name(isTaggedError2, "isTaggedError");
|
|
19550
|
-
function toRagError2(cause, message) {
|
|
19551
|
-
if (isTaggedError2(cause)) {
|
|
19552
|
-
const error48 = {
|
|
19553
|
-
code: cause.code ?? "rag_error",
|
|
19554
|
-
message: `${message}: ${cause.message}`,
|
|
19555
|
-
cause
|
|
19556
|
-
};
|
|
19557
|
-
if (cause.meta) error48.meta = cause.meta;
|
|
19558
|
-
return error48;
|
|
19559
|
-
}
|
|
19560
|
-
return {
|
|
19561
|
-
code: "rag_error",
|
|
19562
|
-
message,
|
|
19563
|
-
cause
|
|
19564
|
-
};
|
|
19565
|
-
}
|
|
19566
|
-
__name(toRagError2, "toRagError");
|
|
19567
19520
|
var DEFAULT_SIGNED_URL_TTL_SECONDS = 3600;
|
|
19568
19521
|
var StorageModule = class {
|
|
19569
19522
|
static {
|
|
@@ -19580,11 +19533,12 @@ var StorageModule = class {
|
|
|
19580
19533
|
return new StorageBucket(bucket, () => this.settings(), this._gate);
|
|
19581
19534
|
}
|
|
19582
19535
|
settings() {
|
|
19583
|
-
const accessKeyId = this._resolved.config.s3?.accessKeyId ?? this._resolved.env["
|
|
19584
|
-
const secretAccessKey = this._resolved.config.s3?.secretAccessKey ?? this._resolved.env["
|
|
19585
|
-
const endpoint = this._resolved.config.s3?.endpoint ?? this._resolved.env["
|
|
19586
|
-
const bucket = this._resolved.config.s3?.bucket ?? this._resolved.env["
|
|
19536
|
+
const accessKeyId = this._resolved.config.s3?.accessKeyId ?? this._resolved.env["STACKBONE_S3_ACCESS_KEY"];
|
|
19537
|
+
const secretAccessKey = this._resolved.config.s3?.secretAccessKey ?? this._resolved.env["STACKBONE_S3_SECRET_KEY"];
|
|
19538
|
+
const endpoint = this._resolved.config.s3?.endpoint ?? this._resolved.env["STACKBONE_S3_ENDPOINT"];
|
|
19539
|
+
const bucket = this._resolved.config.s3?.bucket ?? this._resolved.env["STACKBONE_S3_BUCKET"];
|
|
19587
19540
|
const agentId = this._resolved.config.agentId ?? this._resolved.env["STACKBONE_AGENT_ID"];
|
|
19541
|
+
const region = this._resolved.config.s3?.region ?? this._resolved.env["STACKBONE_S3_REGION"] ?? "auto";
|
|
19588
19542
|
if (!accessKeyId || !secretAccessKey || !endpoint) {
|
|
19589
19543
|
return err({
|
|
19590
19544
|
code: "s3_credentials_missing",
|
|
@@ -19605,7 +19559,7 @@ var StorageModule = class {
|
|
|
19605
19559
|
}
|
|
19606
19560
|
this._s3 ??= new clientS3.S3Client({
|
|
19607
19561
|
endpoint,
|
|
19608
|
-
region
|
|
19562
|
+
region,
|
|
19609
19563
|
forcePathStyle: true,
|
|
19610
19564
|
credentials: {
|
|
19611
19565
|
accessKeyId,
|
|
@@ -19764,29 +19718,19 @@ var StorageBucket = class {
|
|
|
19764
19718
|
return ok(`${base}/${bucket}/${encodeS3Key(fullKey)}`);
|
|
19765
19719
|
}
|
|
19766
19720
|
async getSignedUploadUrl(key, options) {
|
|
19767
|
-
|
|
19768
|
-
|
|
19769
|
-
|
|
19770
|
-
|
|
19771
|
-
|
|
19772
|
-
const expiresIn = options?.expiresIn ?? DEFAULT_SIGNED_URL_TTL_SECONDS;
|
|
19773
|
-
try {
|
|
19774
|
-
const url2 = await s3RequestPresigner.getSignedUrl(client, new clientS3.PutObjectCommand({
|
|
19775
|
-
Bucket: bucket,
|
|
19776
|
-
Key: fullKey,
|
|
19777
|
-
ContentType: options?.contentType
|
|
19778
|
-
}), {
|
|
19779
|
-
expiresIn
|
|
19780
|
-
});
|
|
19781
|
-
return ok({
|
|
19782
|
-
url: url2,
|
|
19783
|
-
expiresAt: new Date(Date.now() + expiresIn * 1e3)
|
|
19784
|
-
});
|
|
19785
|
-
} catch (cause) {
|
|
19786
|
-
return err(toStorageError("Signing upload URL failed", cause));
|
|
19787
|
-
}
|
|
19721
|
+
return this.signUrl(key, options, "Signing upload URL failed", ({ bucket, fullKey }) => new clientS3.PutObjectCommand({
|
|
19722
|
+
Bucket: bucket,
|
|
19723
|
+
Key: fullKey,
|
|
19724
|
+
ContentType: options?.contentType
|
|
19725
|
+
}));
|
|
19788
19726
|
}
|
|
19789
19727
|
async getSignedDownloadUrl(key, options) {
|
|
19728
|
+
return this.signUrl(key, options, "Signing download URL failed", ({ bucket, fullKey }) => new clientS3.GetObjectCommand({
|
|
19729
|
+
Bucket: bucket,
|
|
19730
|
+
Key: fullKey
|
|
19731
|
+
}));
|
|
19732
|
+
}
|
|
19733
|
+
async signUrl(key, options, failureMessage, buildCommand) {
|
|
19790
19734
|
const gateResult = await this.gate();
|
|
19791
19735
|
if (gateResult.error) return err(gateResult.error);
|
|
19792
19736
|
const resolved = this.resolve(key);
|
|
@@ -19794,9 +19738,9 @@ var StorageBucket = class {
|
|
|
19794
19738
|
const { client, bucket, fullKey } = resolved.data;
|
|
19795
19739
|
const expiresIn = options?.expiresIn ?? DEFAULT_SIGNED_URL_TTL_SECONDS;
|
|
19796
19740
|
try {
|
|
19797
|
-
const url2 = await s3RequestPresigner.getSignedUrl(client,
|
|
19798
|
-
|
|
19799
|
-
|
|
19741
|
+
const url2 = await s3RequestPresigner.getSignedUrl(client, buildCommand({
|
|
19742
|
+
bucket,
|
|
19743
|
+
fullKey
|
|
19800
19744
|
}), {
|
|
19801
19745
|
expiresIn
|
|
19802
19746
|
});
|
|
@@ -19805,7 +19749,7 @@ var StorageBucket = class {
|
|
|
19805
19749
|
expiresAt: new Date(Date.now() + expiresIn * 1e3)
|
|
19806
19750
|
});
|
|
19807
19751
|
} catch (cause) {
|
|
19808
|
-
return err(toStorageError(
|
|
19752
|
+
return err(toStorageError(failureMessage, cause));
|
|
19809
19753
|
}
|
|
19810
19754
|
}
|
|
19811
19755
|
/**
|
|
@@ -19831,8 +19775,8 @@ var StorageBucket = class {
|
|
|
19831
19775
|
});
|
|
19832
19776
|
}
|
|
19833
19777
|
};
|
|
19834
|
-
var S3_CREDENTIALS_MISSING_MESSAGE = "Cannot reach object storage \u2014 set `
|
|
19835
|
-
var S3_BUCKET_MISSING_MESSAGE = "No storage bucket configured \u2014 set `
|
|
19778
|
+
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({...})`.";
|
|
19779
|
+
var S3_BUCKET_MISSING_MESSAGE = "No storage bucket configured \u2014 set `STACKBONE_S3_BUCKET` in the container or pass `s3.bucket` to `createClient({...})`.";
|
|
19836
19780
|
var AGENT_ID_MISSING_MESSAGE = "No agent identity configured \u2014 set `STACKBONE_AGENT_ID` in the container or pass `agentId` to `createClient({...})`.";
|
|
19837
19781
|
function stripEtag(etag) {
|
|
19838
19782
|
return etag?.replace(/^"|"$/g, "");
|