@granular-software/sdk 0.4.8 → 0.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +136 -1
- package/dist/index.d.ts +136 -1
- package/dist/index.js +303 -111
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +303 -111
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3972,6 +3972,9 @@ var WSClient = class {
|
|
|
3972
3972
|
this.sessionId = options.sessionId;
|
|
3973
3973
|
this.token = options.token;
|
|
3974
3974
|
}
|
|
3975
|
+
get currentSessionId() {
|
|
3976
|
+
return this.sessionId;
|
|
3977
|
+
}
|
|
3975
3978
|
clearTokenRefreshTimer() {
|
|
3976
3979
|
if (this.tokenRefreshTimer) {
|
|
3977
3980
|
clearTimeout(this.tokenRefreshTimer);
|
|
@@ -4525,6 +4528,9 @@ var Session = class {
|
|
|
4525
4528
|
get document() {
|
|
4526
4529
|
return this.client.doc;
|
|
4527
4530
|
}
|
|
4531
|
+
get sessionId() {
|
|
4532
|
+
return this.client.currentSessionId;
|
|
4533
|
+
}
|
|
4528
4534
|
get domainRevision() {
|
|
4529
4535
|
return this.currentDomainRevision;
|
|
4530
4536
|
}
|
|
@@ -4620,7 +4626,11 @@ var Session = class {
|
|
|
4620
4626
|
if (!result.jobId) {
|
|
4621
4627
|
throw new Error("Failed to submit job: no jobId returned");
|
|
4622
4628
|
}
|
|
4623
|
-
const job = new JobImplementation(result.jobId, this.client
|
|
4629
|
+
const job = new JobImplementation(result.jobId, this.client, {
|
|
4630
|
+
code,
|
|
4631
|
+
domainRevision: revision,
|
|
4632
|
+
createdAt: Date.now()
|
|
4633
|
+
});
|
|
4624
4634
|
this.jobsMap.set(result.jobId, job);
|
|
4625
4635
|
return job;
|
|
4626
4636
|
}
|
|
@@ -5014,6 +5024,78 @@ import { ${allImports} } from "./sandbox-tools";
|
|
|
5014
5024
|
}
|
|
5015
5025
|
}
|
|
5016
5026
|
};
|
|
5027
|
+
var MAX_FEEDBACK_STRING_LENGTH = 16e3;
|
|
5028
|
+
var MAX_FEEDBACK_TOOL_CALLS = 50;
|
|
5029
|
+
var MAX_FEEDBACK_ARRAY_ITEMS = 50;
|
|
5030
|
+
var MAX_FEEDBACK_OBJECT_KEYS = 50;
|
|
5031
|
+
var MAX_FEEDBACK_DEPTH = 6;
|
|
5032
|
+
function truncateFeedbackString(value, maxLength = MAX_FEEDBACK_STRING_LENGTH) {
|
|
5033
|
+
if (value.length <= maxLength) {
|
|
5034
|
+
return value;
|
|
5035
|
+
}
|
|
5036
|
+
return `${value.slice(0, maxLength)}...[truncated ${value.length - maxLength} chars]`;
|
|
5037
|
+
}
|
|
5038
|
+
function normalizeJobStatus(status) {
|
|
5039
|
+
if (typeof status !== "string") {
|
|
5040
|
+
return "queued";
|
|
5041
|
+
}
|
|
5042
|
+
switch (status) {
|
|
5043
|
+
case "completed":
|
|
5044
|
+
return "succeeded";
|
|
5045
|
+
case "failed":
|
|
5046
|
+
case "running":
|
|
5047
|
+
case "queued":
|
|
5048
|
+
case "succeeded":
|
|
5049
|
+
case "timeout":
|
|
5050
|
+
case "canceled":
|
|
5051
|
+
return status;
|
|
5052
|
+
default:
|
|
5053
|
+
return "queued";
|
|
5054
|
+
}
|
|
5055
|
+
}
|
|
5056
|
+
function sanitizeFeedbackValue(value, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {
|
|
5057
|
+
if (depth >= MAX_FEEDBACK_DEPTH) {
|
|
5058
|
+
return "[Max depth reached]";
|
|
5059
|
+
}
|
|
5060
|
+
if (value === null || value === void 0) {
|
|
5061
|
+
return null;
|
|
5062
|
+
}
|
|
5063
|
+
if (typeof value === "string") {
|
|
5064
|
+
return truncateFeedbackString(value);
|
|
5065
|
+
}
|
|
5066
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
5067
|
+
return value;
|
|
5068
|
+
}
|
|
5069
|
+
if (typeof value === "bigint") {
|
|
5070
|
+
return truncateFeedbackString(value.toString());
|
|
5071
|
+
}
|
|
5072
|
+
if (value instanceof Error) {
|
|
5073
|
+
return {
|
|
5074
|
+
name: truncateFeedbackString(value.name),
|
|
5075
|
+
message: truncateFeedbackString(value.message),
|
|
5076
|
+
stack: truncateFeedbackString(value.stack || "")
|
|
5077
|
+
};
|
|
5078
|
+
}
|
|
5079
|
+
if (value instanceof Date) {
|
|
5080
|
+
return value.toISOString();
|
|
5081
|
+
}
|
|
5082
|
+
if (Array.isArray(value)) {
|
|
5083
|
+
return value.slice(0, MAX_FEEDBACK_ARRAY_ITEMS).map((entry) => sanitizeFeedbackValue(entry, depth + 1, seen));
|
|
5084
|
+
}
|
|
5085
|
+
if (typeof value === "object") {
|
|
5086
|
+
if (seen.has(value)) {
|
|
5087
|
+
return "[Circular]";
|
|
5088
|
+
}
|
|
5089
|
+
seen.add(value);
|
|
5090
|
+
const entries = Object.entries(value).slice(0, MAX_FEEDBACK_OBJECT_KEYS);
|
|
5091
|
+
const sanitized = {};
|
|
5092
|
+
for (const [key, entryValue] of entries) {
|
|
5093
|
+
sanitized[key] = sanitizeFeedbackValue(entryValue, depth + 1, seen);
|
|
5094
|
+
}
|
|
5095
|
+
return sanitized;
|
|
5096
|
+
}
|
|
5097
|
+
return truncateFeedbackString(String(value));
|
|
5098
|
+
}
|
|
5017
5099
|
var JobImplementation = class {
|
|
5018
5100
|
id;
|
|
5019
5101
|
client;
|
|
@@ -5022,9 +5104,20 @@ var JobImplementation = class {
|
|
|
5022
5104
|
_resolveResult;
|
|
5023
5105
|
_rejectResult;
|
|
5024
5106
|
eventListeners = /* @__PURE__ */ new Map();
|
|
5025
|
-
|
|
5107
|
+
metadata;
|
|
5108
|
+
constructor(id, client, initialState) {
|
|
5026
5109
|
this.id = id;
|
|
5027
5110
|
this.client = client;
|
|
5111
|
+
this.metadata = {
|
|
5112
|
+
source: "sdk",
|
|
5113
|
+
status: "queued",
|
|
5114
|
+
code: truncateFeedbackString(initialState.code),
|
|
5115
|
+
domainRevision: initialState.domainRevision,
|
|
5116
|
+
createdAt: initialState.createdAt,
|
|
5117
|
+
stdout: [],
|
|
5118
|
+
stderr: [],
|
|
5119
|
+
toolCalls: []
|
|
5120
|
+
};
|
|
5028
5121
|
this._resultPromise = new Promise((resolve, reject) => {
|
|
5029
5122
|
this._resolveResult = resolve;
|
|
5030
5123
|
this._rejectResult = reject;
|
|
@@ -5032,69 +5125,98 @@ var JobImplementation = class {
|
|
|
5032
5125
|
this.client.on("exec.completed", (data) => {
|
|
5033
5126
|
const execData = data;
|
|
5034
5127
|
if (execData.execId === id || execData.jobId === id) {
|
|
5035
|
-
this.status = "succeeded";
|
|
5036
|
-
this.emit("status", this.status);
|
|
5037
5128
|
if (execData.error) {
|
|
5038
|
-
this.
|
|
5129
|
+
this.finalize("failed", void 0, execData.error);
|
|
5039
5130
|
} else {
|
|
5040
|
-
this.
|
|
5131
|
+
this.finalize("succeeded", execData.result);
|
|
5041
5132
|
}
|
|
5133
|
+
this.emit("status", this.status);
|
|
5042
5134
|
}
|
|
5043
5135
|
});
|
|
5044
5136
|
this.client.on("exec.progress", (data) => {
|
|
5045
5137
|
const progressData = data;
|
|
5046
5138
|
if (progressData.execId === id || progressData.jobId === id) {
|
|
5047
5139
|
if (progressData.stdout) {
|
|
5140
|
+
this.markStarted();
|
|
5141
|
+
this.metadata.stdout = [...this.metadata.stdout, truncateFeedbackString(progressData.stdout)].slice(-100);
|
|
5048
5142
|
this.emit("stdout", progressData.stdout);
|
|
5049
5143
|
}
|
|
5050
5144
|
if (progressData.stderr) {
|
|
5145
|
+
this.markStarted();
|
|
5146
|
+
this.metadata.stderr = [...this.metadata.stderr, truncateFeedbackString(progressData.stderr)].slice(-100);
|
|
5051
5147
|
this.emit("stderr", progressData.stderr);
|
|
5052
5148
|
}
|
|
5053
5149
|
}
|
|
5054
5150
|
});
|
|
5055
5151
|
this.client.on(`job.${id}.status`, (status) => {
|
|
5056
|
-
|
|
5057
|
-
this.
|
|
5152
|
+
const normalizedStatus = normalizeJobStatus(status);
|
|
5153
|
+
this.status = normalizedStatus;
|
|
5154
|
+
this.metadata.status = normalizedStatus;
|
|
5155
|
+
if (normalizedStatus === "running") {
|
|
5156
|
+
this.markStarted();
|
|
5157
|
+
}
|
|
5158
|
+
if (normalizedStatus === "failed" || normalizedStatus === "timeout" || normalizedStatus === "canceled") {
|
|
5159
|
+
this.finalize(normalizedStatus);
|
|
5160
|
+
}
|
|
5161
|
+
if (normalizedStatus === "succeeded") {
|
|
5162
|
+
this.finalize("succeeded");
|
|
5163
|
+
}
|
|
5164
|
+
this.emit("status", normalizedStatus);
|
|
5058
5165
|
});
|
|
5059
5166
|
this.client.on(`job.${id}.stdout`, (line) => {
|
|
5167
|
+
this.markStarted();
|
|
5168
|
+
this.metadata.stdout = [...this.metadata.stdout, truncateFeedbackString(String(line))].slice(-100);
|
|
5060
5169
|
this.emit("stdout", line);
|
|
5061
5170
|
});
|
|
5062
5171
|
this.client.on(`job.${id}.stderr`, (line) => {
|
|
5172
|
+
this.markStarted();
|
|
5173
|
+
this.metadata.stderr = [...this.metadata.stderr, truncateFeedbackString(String(line))].slice(-100);
|
|
5063
5174
|
this.emit("stderr", line);
|
|
5064
5175
|
});
|
|
5065
5176
|
this.client.on(`job.${id}.result`, (result) => {
|
|
5066
|
-
this.
|
|
5067
|
-
this._resolveResult(result);
|
|
5177
|
+
this.finalize("succeeded", result);
|
|
5068
5178
|
});
|
|
5069
5179
|
this.client.on(`job.${id}.error`, (error) => {
|
|
5070
|
-
this.
|
|
5071
|
-
this._rejectResult(error);
|
|
5180
|
+
this.finalize("failed", void 0, error);
|
|
5072
5181
|
});
|
|
5073
5182
|
this.client.on("job.completed", (data) => {
|
|
5074
5183
|
const jobData = data;
|
|
5075
5184
|
if (jobData.jobId === id) {
|
|
5076
|
-
this.
|
|
5185
|
+
this.finalize("succeeded", jobData.result);
|
|
5077
5186
|
this.emit("status", this.status);
|
|
5078
|
-
this._resolveResult(jobData.result);
|
|
5079
5187
|
}
|
|
5080
5188
|
});
|
|
5081
5189
|
this.client.on("job.failed", (data) => {
|
|
5082
5190
|
const jobData = data;
|
|
5083
5191
|
if (jobData.jobId === id) {
|
|
5084
|
-
this.
|
|
5192
|
+
this.finalize("failed", void 0, jobData.error || new Error("Job failed"));
|
|
5085
5193
|
this.emit("status", this.status);
|
|
5086
|
-
this._rejectResult(jobData.error || new Error("Job failed"));
|
|
5087
5194
|
}
|
|
5088
5195
|
});
|
|
5089
5196
|
this.client.on("tool.call.start", (data) => {
|
|
5090
5197
|
const d = data;
|
|
5091
5198
|
if (d.jobId === id) {
|
|
5199
|
+
this.metadata.toolCalls = this.upsertToolCall({
|
|
5200
|
+
callId: d.callId,
|
|
5201
|
+
toolName: d.toolName,
|
|
5202
|
+
input: sanitizeFeedbackValue(d.input),
|
|
5203
|
+
startedAt: d.timestamp || Date.now()
|
|
5204
|
+
});
|
|
5092
5205
|
this.emit("toolCallStart", { callId: d.callId, toolName: d.toolName, input: d.input, timestamp: d.timestamp });
|
|
5093
5206
|
}
|
|
5094
5207
|
});
|
|
5095
5208
|
this.client.on("tool.call.end", (data) => {
|
|
5096
5209
|
const d = data;
|
|
5097
5210
|
if (d.jobId === id) {
|
|
5211
|
+
const completedAt = d.timestamp || Date.now();
|
|
5212
|
+
this.metadata.toolCalls = this.upsertToolCall({
|
|
5213
|
+
callId: d.callId,
|
|
5214
|
+
toolName: d.toolName,
|
|
5215
|
+
output: sanitizeFeedbackValue(d.result),
|
|
5216
|
+
error: d.error ? truncateFeedbackString(d.error) : void 0,
|
|
5217
|
+
completedAt,
|
|
5218
|
+
durationMs: typeof d.durationMs === "number" ? d.durationMs : void 0
|
|
5219
|
+
});
|
|
5098
5220
|
this.emit("toolCallEnd", { callId: d.callId, toolName: d.toolName, result: d.result, error: d.error, durationMs: d.durationMs, timestamp: d.timestamp });
|
|
5099
5221
|
}
|
|
5100
5222
|
});
|
|
@@ -5102,12 +5224,87 @@ var JobImplementation = class {
|
|
|
5102
5224
|
get result() {
|
|
5103
5225
|
return this._resultPromise;
|
|
5104
5226
|
}
|
|
5227
|
+
async leaveFeedback(input) {
|
|
5228
|
+
const sentiment = input.sentiment;
|
|
5229
|
+
if (sentiment !== "good" && sentiment !== "bad") {
|
|
5230
|
+
throw new Error('Job feedback sentiment must be "good" or "bad".');
|
|
5231
|
+
}
|
|
5232
|
+
const comment = typeof input.comment === "string" ? input.comment.trim() : "";
|
|
5233
|
+
const response = await this.client.call("job.feedback", {
|
|
5234
|
+
jobId: this.id,
|
|
5235
|
+
sentiment,
|
|
5236
|
+
comment: comment || void 0,
|
|
5237
|
+
metadata: this.buildFeedbackMetadata()
|
|
5238
|
+
});
|
|
5239
|
+
this.emit("feedback", response);
|
|
5240
|
+
return response;
|
|
5241
|
+
}
|
|
5105
5242
|
on(event, handler) {
|
|
5106
5243
|
if (!this.eventListeners.has(event)) {
|
|
5107
5244
|
this.eventListeners.set(event, []);
|
|
5108
5245
|
}
|
|
5109
5246
|
this.eventListeners.get(event).push(handler);
|
|
5110
5247
|
}
|
|
5248
|
+
buildFeedbackMetadata() {
|
|
5249
|
+
const startedAt = this.metadata.startedAt;
|
|
5250
|
+
const completedAt = this.metadata.completedAt;
|
|
5251
|
+
return {
|
|
5252
|
+
...this.metadata,
|
|
5253
|
+
durationMs: typeof startedAt === "number" && typeof completedAt === "number" ? completedAt - startedAt : this.metadata.durationMs ?? null,
|
|
5254
|
+
stdout: [...this.metadata.stdout],
|
|
5255
|
+
stderr: [...this.metadata.stderr],
|
|
5256
|
+
toolCalls: this.metadata.toolCalls.slice(0, MAX_FEEDBACK_TOOL_CALLS).map((call) => ({ ...call }))
|
|
5257
|
+
};
|
|
5258
|
+
}
|
|
5259
|
+
markStarted(timestamp = Date.now()) {
|
|
5260
|
+
if (!this.metadata.startedAt) {
|
|
5261
|
+
this.metadata.startedAt = timestamp;
|
|
5262
|
+
}
|
|
5263
|
+
if (this.status === "queued") {
|
|
5264
|
+
this.status = "running";
|
|
5265
|
+
}
|
|
5266
|
+
if (this.metadata.status === "queued") {
|
|
5267
|
+
this.metadata.status = "running";
|
|
5268
|
+
}
|
|
5269
|
+
}
|
|
5270
|
+
finalize(status, result, error) {
|
|
5271
|
+
if (!this.metadata.startedAt) {
|
|
5272
|
+
this.metadata.startedAt = Date.now();
|
|
5273
|
+
}
|
|
5274
|
+
this.status = status;
|
|
5275
|
+
this.metadata.status = status;
|
|
5276
|
+
this.metadata.completedAt = this.metadata.completedAt || Date.now();
|
|
5277
|
+
this.metadata.durationMs = this.metadata.completedAt - this.metadata.startedAt;
|
|
5278
|
+
if (result !== void 0) {
|
|
5279
|
+
this.metadata.result = sanitizeFeedbackValue(result);
|
|
5280
|
+
this._resolveResult(result);
|
|
5281
|
+
}
|
|
5282
|
+
if (error !== void 0) {
|
|
5283
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
5284
|
+
this.metadata.error = truncateFeedbackString(message);
|
|
5285
|
+
this._rejectResult(error);
|
|
5286
|
+
}
|
|
5287
|
+
}
|
|
5288
|
+
upsertToolCall(next) {
|
|
5289
|
+
const callId = next.callId || `tool-call-${Date.now()}`;
|
|
5290
|
+
const existingIndex = this.metadata.toolCalls.findIndex((entry) => entry.callId === callId);
|
|
5291
|
+
const existing = existingIndex >= 0 ? this.metadata.toolCalls[existingIndex] : void 0;
|
|
5292
|
+
const merged = {
|
|
5293
|
+
...existing,
|
|
5294
|
+
...next,
|
|
5295
|
+
callId,
|
|
5296
|
+
toolName: next.toolName || existing?.toolName
|
|
5297
|
+
};
|
|
5298
|
+
if (merged.durationMs === void 0 && typeof merged.startedAt === "number" && typeof merged.completedAt === "number") {
|
|
5299
|
+
merged.durationMs = merged.completedAt - merged.startedAt;
|
|
5300
|
+
}
|
|
5301
|
+
if (existingIndex >= 0) {
|
|
5302
|
+
const updated = [...this.metadata.toolCalls];
|
|
5303
|
+
updated[existingIndex] = merged;
|
|
5304
|
+
return updated.slice(-MAX_FEEDBACK_TOOL_CALLS);
|
|
5305
|
+
}
|
|
5306
|
+
return [...this.metadata.toolCalls, merged].slice(-MAX_FEEDBACK_TOOL_CALLS);
|
|
5307
|
+
}
|
|
5111
5308
|
emit(event, data) {
|
|
5112
5309
|
const handlers = this.eventListeners.get(event);
|
|
5113
5310
|
if (handlers) {
|
|
@@ -5248,7 +5445,7 @@ function normalizeUser(user) {
|
|
|
5248
5445
|
permissions: Array.isArray(user.permissions) ? user.permissions : []
|
|
5249
5446
|
};
|
|
5250
5447
|
}
|
|
5251
|
-
var Environment = class
|
|
5448
|
+
var Environment = class extends Session {
|
|
5252
5449
|
envData;
|
|
5253
5450
|
_apiKey;
|
|
5254
5451
|
_apiEndpoint;
|
|
@@ -5308,6 +5505,22 @@ var Environment = class _Environment extends Session {
|
|
|
5308
5505
|
return this._apiEndpoint.replace(/\/orchestrator\/graphql$/, "").replace(/\/$/, "");
|
|
5309
5506
|
}
|
|
5310
5507
|
}
|
|
5508
|
+
async controlPlaneRequest(path, options = {}) {
|
|
5509
|
+
const runtimeBase = this.getRuntimeBaseUrl();
|
|
5510
|
+
const url = `${runtimeBase}${path}`;
|
|
5511
|
+
const response = await fetch(url, {
|
|
5512
|
+
...options,
|
|
5513
|
+
headers: {
|
|
5514
|
+
"Authorization": `Bearer ${this._apiKey}`,
|
|
5515
|
+
"Content-Type": "application/json",
|
|
5516
|
+
...options.headers
|
|
5517
|
+
}
|
|
5518
|
+
});
|
|
5519
|
+
if (!response.ok) {
|
|
5520
|
+
throw new Error(`Control Plane API Error (${response.status}): ${await response.text()}`);
|
|
5521
|
+
}
|
|
5522
|
+
return response.json();
|
|
5523
|
+
}
|
|
5311
5524
|
/**
|
|
5312
5525
|
* Close the session and disconnect from the sandbox.
|
|
5313
5526
|
*
|
|
@@ -5904,105 +6117,84 @@ var Environment = class _Environment extends Session {
|
|
|
5904
6117
|
* ```
|
|
5905
6118
|
*/
|
|
5906
6119
|
async recordObject(options) {
|
|
5907
|
-
const
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
6120
|
+
const results = await this.recordObjects([options]);
|
|
6121
|
+
return results[0];
|
|
6122
|
+
}
|
|
6123
|
+
/**
|
|
6124
|
+
* Batch version of `recordObject()`.
|
|
6125
|
+
*
|
|
6126
|
+
* Sends several upserts through the control-plane batch endpoint so the
|
|
6127
|
+
* server can collapse the graph mutations into far fewer round trips.
|
|
6128
|
+
*/
|
|
6129
|
+
async recordObjects(records) {
|
|
6130
|
+
if (!Array.isArray(records) || records.length === 0) {
|
|
6131
|
+
return [];
|
|
6132
|
+
}
|
|
6133
|
+
const response = await this.controlPlaneRequest(
|
|
6134
|
+
`/control/environments/${this.environmentId}/records/batch`,
|
|
6135
|
+
{
|
|
6136
|
+
method: "POST",
|
|
6137
|
+
body: JSON.stringify({ records })
|
|
6138
|
+
}
|
|
5911
6139
|
);
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
6140
|
+
return Array.isArray(response.items) ? response.items : [];
|
|
6141
|
+
}
|
|
6142
|
+
/**
|
|
6143
|
+
* Queue a background record import for this environment.
|
|
6144
|
+
*/
|
|
6145
|
+
async enqueueRecordImport(records, options = {}) {
|
|
6146
|
+
return this.controlPlaneRequest(
|
|
6147
|
+
`/control/environments/${this.environmentId}/record-imports`,
|
|
6148
|
+
{
|
|
6149
|
+
method: "POST",
|
|
6150
|
+
body: JSON.stringify({
|
|
6151
|
+
records,
|
|
6152
|
+
batchSize: options.batchSize
|
|
6153
|
+
})
|
|
6154
|
+
}
|
|
5921
6155
|
);
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
model { path }
|
|
5931
|
-
}
|
|
5932
|
-
}
|
|
5933
|
-
}`
|
|
6156
|
+
}
|
|
6157
|
+
/**
|
|
6158
|
+
* List queued or completed record imports for this environment.
|
|
6159
|
+
*/
|
|
6160
|
+
async listRecordImports(status) {
|
|
6161
|
+
const suffix = status ? `?status=${encodeURIComponent(status)}` : "";
|
|
6162
|
+
const response = await this.controlPlaneRequest(
|
|
6163
|
+
`/control/environments/${this.environmentId}/record-imports${suffix}`
|
|
5934
6164
|
);
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
6165
|
+
return Array.isArray(response.items) ? response.items : [];
|
|
6166
|
+
}
|
|
6167
|
+
/**
|
|
6168
|
+
* Fetch the latest aggregate import counters for this environment.
|
|
6169
|
+
*/
|
|
6170
|
+
async getRecordImportSummary() {
|
|
6171
|
+
return this.controlPlaneRequest(
|
|
6172
|
+
`/control/environments/${this.environmentId}/record-imports/summary`
|
|
5943
6173
|
);
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
} else if (typeof value === "number") {
|
|
5967
|
-
await this.graphql(
|
|
5968
|
-
`mutation {
|
|
5969
|
-
at(path: "${instancePath}") {
|
|
5970
|
-
at(submodel: "${fieldName}") {
|
|
5971
|
-
set_number_value(value: ${value}) { done }
|
|
5972
|
-
}
|
|
5973
|
-
}
|
|
5974
|
-
}`
|
|
5975
|
-
);
|
|
5976
|
-
} else if (typeof value === "boolean") {
|
|
5977
|
-
await this.graphql(
|
|
5978
|
-
`mutation {
|
|
5979
|
-
at(path: "${instancePath}") {
|
|
5980
|
-
at(submodel: "${fieldName}") {
|
|
5981
|
-
set_boolean_value(value: ${value}) { done }
|
|
5982
|
-
}
|
|
5983
|
-
}
|
|
5984
|
-
}`
|
|
5985
|
-
);
|
|
5986
|
-
}
|
|
5987
|
-
}
|
|
5988
|
-
}
|
|
5989
|
-
if (relationships) {
|
|
5990
|
-
const rels = await this.getRelationships(className);
|
|
5991
|
-
const relMap = {};
|
|
5992
|
-
for (const rel of rels) {
|
|
5993
|
-
const submodelLeaf = rel.local_submodel.path.includes(":") ? rel.local_submodel.path.split(":").pop() : rel.local_submodel.path;
|
|
5994
|
-
relMap[submodelLeaf] = rel.foreign_model.path;
|
|
5995
|
-
}
|
|
5996
|
-
for (const [submodelName, targets] of Object.entries(relationships)) {
|
|
5997
|
-
const foreignClass = relMap[submodelName];
|
|
5998
|
-
const targetList = Array.isArray(targets) ? targets : [targets];
|
|
5999
|
-
for (const target of targetList) {
|
|
6000
|
-
const targetGraphPath = foreignClass ? _Environment.toGraphPath(foreignClass, target) : target;
|
|
6001
|
-
await this.attach(instancePath, submodelName, targetGraphPath);
|
|
6002
|
-
}
|
|
6174
|
+
}
|
|
6175
|
+
/**
|
|
6176
|
+
* Convenience helper returning queued + processing records for this environment.
|
|
6177
|
+
*/
|
|
6178
|
+
async getAwaitingRecordCount() {
|
|
6179
|
+
const summary = await this.getRecordImportSummary();
|
|
6180
|
+
return summary.awaitingRecords;
|
|
6181
|
+
}
|
|
6182
|
+
/**
|
|
6183
|
+
* Fetch a single record import by id.
|
|
6184
|
+
*/
|
|
6185
|
+
async getRecordImport(importId) {
|
|
6186
|
+
return this.controlPlaneRequest(`/control/record-imports/${importId}`);
|
|
6187
|
+
}
|
|
6188
|
+
/**
|
|
6189
|
+
* Cancel a queued/background record import.
|
|
6190
|
+
*/
|
|
6191
|
+
async cancelRecordImport(importId) {
|
|
6192
|
+
return this.controlPlaneRequest(
|
|
6193
|
+
`/control/record-imports/${importId}/cancel`,
|
|
6194
|
+
{
|
|
6195
|
+
method: "POST"
|
|
6003
6196
|
}
|
|
6004
|
-
|
|
6005
|
-
return { path: instancePath, id, created: !alreadyExists };
|
|
6197
|
+
);
|
|
6006
6198
|
}
|
|
6007
6199
|
// ==================== PUBLISH TOOLS ====================
|
|
6008
6200
|
/**
|