@granular-software/sdk 0.4.31 → 0.4.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/dist/agent-evals.d.mts +1 -1
- package/dist/agent-evals.d.ts +1 -1
- package/dist/agent-evals.js +812 -313
- package/dist/agent-evals.js.map +1 -1
- package/dist/agent-evals.mjs +812 -313
- package/dist/agent-evals.mjs.map +1 -1
- package/dist/cli/index.js +813 -59
- package/dist/{client-CTH1hfwe.d.mts → client-DTvI5MUG.d.mts} +112 -19
- package/dist/{client-CTH1hfwe.d.ts → client-DTvI5MUG.d.ts} +112 -19
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +7864 -7665
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7864 -7665
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -15222,7 +15222,8 @@ ${effectMetamodelTable}
|
|
|
15222
15222
|
| \`getDomain()\`, \`getDomainTypes()\`, \`getDomainDocs()\`, \`getDomainDocumentation()\` | Domain summary and generated TypeScript / docs. |
|
|
15223
15223
|
| \`getEffects()\` / \`getTools()\`, \`session.on("effects:changed", ...)\` | Effect catalog and live updates. |
|
|
15224
15224
|
| \`checkReadiness()\`, \`on('readiness', ...)\` | Runtime readiness. |
|
|
15225
|
-
| \`getHeap()\` |
|
|
15225
|
+
| \`document\`, \`getHeap()\` | Current live session state from the WebSocket. |
|
|
15226
|
+
| \`messages.list()\`, \`timeline.list()\`, \`jobs.list/get()\`, \`heap.entries.list/get()\`, \`heap.lists.list/get()\`, \`transcript.list()\` | Durable session history and saved artifacts. |
|
|
15226
15227
|
| \`disconnect()\` | Close the live runtime session. |
|
|
15227
15228
|
| \`rpc(method, params)\` | Low-level session RPC (advanced). |
|
|
15228
15229
|
| \`disconnect()\` | End the session. |
|
|
@@ -17779,7 +17780,11 @@ var WSClient = class {
|
|
|
17779
17780
|
return null;
|
|
17780
17781
|
}
|
|
17781
17782
|
try {
|
|
17782
|
-
const
|
|
17783
|
+
const payloadSegment = parts[1];
|
|
17784
|
+
if (!payloadSegment) {
|
|
17785
|
+
return null;
|
|
17786
|
+
}
|
|
17787
|
+
const payloadRaw = this.decodeBase64Url(payloadSegment);
|
|
17783
17788
|
const payload = JSON.parse(payloadRaw);
|
|
17784
17789
|
if (typeof payload.exp !== "number" || !Number.isFinite(payload.exp)) {
|
|
17785
17790
|
return null;
|
|
@@ -18856,6 +18861,7 @@ import { ${allImports} } from "./sandbox-tools";
|
|
|
18856
18861
|
this.eventListeners.set(event, []);
|
|
18857
18862
|
}
|
|
18858
18863
|
this.eventListeners.get(event).push(handler);
|
|
18864
|
+
return () => this.off(event, handler);
|
|
18859
18865
|
}
|
|
18860
18866
|
/**
|
|
18861
18867
|
* Unsubscribe from session events
|
|
@@ -19312,6 +19318,16 @@ var JobImplementation = class {
|
|
|
19312
19318
|
handler(message);
|
|
19313
19319
|
}
|
|
19314
19320
|
}
|
|
19321
|
+
return () => {
|
|
19322
|
+
const handlers = this.eventListeners.get(event);
|
|
19323
|
+
if (!handlers) {
|
|
19324
|
+
return;
|
|
19325
|
+
}
|
|
19326
|
+
this.eventListeners.set(
|
|
19327
|
+
event,
|
|
19328
|
+
handlers.filter((current) => current !== handler)
|
|
19329
|
+
);
|
|
19330
|
+
};
|
|
19315
19331
|
}
|
|
19316
19332
|
replayAgentMessage(message) {
|
|
19317
19333
|
this.captureAgentMessage(message);
|
|
@@ -19398,6 +19414,540 @@ var JobImplementation = class {
|
|
|
19398
19414
|
}
|
|
19399
19415
|
};
|
|
19400
19416
|
|
|
19417
|
+
// src/job-presentation.ts
|
|
19418
|
+
var RESPONSE_KEYS = [
|
|
19419
|
+
"reply",
|
|
19420
|
+
"response",
|
|
19421
|
+
"text",
|
|
19422
|
+
"message",
|
|
19423
|
+
"summary",
|
|
19424
|
+
"answer"
|
|
19425
|
+
];
|
|
19426
|
+
var ENTRY_KEY_CANDIDATES = ["entryPath", "path"];
|
|
19427
|
+
var ENTRY_ARRAY_KEY_CANDIDATES = ["entryPaths", "paths"];
|
|
19428
|
+
var LIST_KEY_CANDIDATES = ["listName"];
|
|
19429
|
+
var LIST_ARRAY_KEY_CANDIDATES = ["listNames"];
|
|
19430
|
+
var VARIABLE_KEY_CANDIDATES = ["variableName"];
|
|
19431
|
+
var VARIABLE_ARRAY_KEY_CANDIDATES = ["variableNames"];
|
|
19432
|
+
var UI_CONTAINER_KEYS = ["show", "display", "present", "ui"];
|
|
19433
|
+
function asRecord2(value) {
|
|
19434
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
19435
|
+
return value;
|
|
19436
|
+
}
|
|
19437
|
+
function normalizeText(value) {
|
|
19438
|
+
if (typeof value !== "string") return null;
|
|
19439
|
+
const trimmed = value.trim();
|
|
19440
|
+
if (!trimmed) return null;
|
|
19441
|
+
if (trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
19442
|
+
return null;
|
|
19443
|
+
}
|
|
19444
|
+
return trimmed;
|
|
19445
|
+
}
|
|
19446
|
+
function humanTextFromStdout(stdout) {
|
|
19447
|
+
for (const line of [...stdout].reverse()) {
|
|
19448
|
+
const normalized = normalizeText(line);
|
|
19449
|
+
if (!normalized) continue;
|
|
19450
|
+
if (/^[A-Z_]+:/.test(normalized)) continue;
|
|
19451
|
+
return normalized;
|
|
19452
|
+
}
|
|
19453
|
+
return null;
|
|
19454
|
+
}
|
|
19455
|
+
function pushString(target, value) {
|
|
19456
|
+
if (typeof value === "string" && value.trim()) {
|
|
19457
|
+
target.add(value.trim());
|
|
19458
|
+
}
|
|
19459
|
+
}
|
|
19460
|
+
function pushStringArray(target, value) {
|
|
19461
|
+
if (!Array.isArray(value)) return;
|
|
19462
|
+
for (const item of value) {
|
|
19463
|
+
pushString(target, item);
|
|
19464
|
+
}
|
|
19465
|
+
}
|
|
19466
|
+
function collectReferencesFromRecord(record, refs) {
|
|
19467
|
+
for (const key of ENTRY_KEY_CANDIDATES)
|
|
19468
|
+
pushString(refs.entryPaths, record[key]);
|
|
19469
|
+
for (const key of ENTRY_ARRAY_KEY_CANDIDATES)
|
|
19470
|
+
pushStringArray(refs.entryPaths, record[key]);
|
|
19471
|
+
for (const key of LIST_KEY_CANDIDATES)
|
|
19472
|
+
pushString(refs.listNames, record[key]);
|
|
19473
|
+
for (const key of LIST_ARRAY_KEY_CANDIDATES)
|
|
19474
|
+
pushStringArray(refs.listNames, record[key]);
|
|
19475
|
+
for (const key of VARIABLE_KEY_CANDIDATES)
|
|
19476
|
+
pushString(refs.variableNames, record[key]);
|
|
19477
|
+
for (const key of VARIABLE_ARRAY_KEY_CANDIDATES)
|
|
19478
|
+
pushStringArray(refs.variableNames, record[key]);
|
|
19479
|
+
}
|
|
19480
|
+
function scanForHeapReferences(value, heap, refs, depth = 0, seen = /* @__PURE__ */ new Set()) {
|
|
19481
|
+
if (value === null || value === void 0 || depth > 4 || seen.has(value))
|
|
19482
|
+
return;
|
|
19483
|
+
if (typeof value === "string") {
|
|
19484
|
+
const trimmed = value.trim();
|
|
19485
|
+
if (heap.entriesByPath?.[trimmed]) refs.entryPaths.add(trimmed);
|
|
19486
|
+
if (heap.listsByName?.[trimmed]) refs.listNames.add(trimmed);
|
|
19487
|
+
if (heap.variablesByName?.[trimmed]) refs.variableNames.add(trimmed);
|
|
19488
|
+
return;
|
|
19489
|
+
}
|
|
19490
|
+
if (Array.isArray(value)) {
|
|
19491
|
+
seen.add(value);
|
|
19492
|
+
for (const item of value.slice(0, 24)) {
|
|
19493
|
+
scanForHeapReferences(item, heap, refs, depth + 1, seen);
|
|
19494
|
+
}
|
|
19495
|
+
return;
|
|
19496
|
+
}
|
|
19497
|
+
const record = asRecord2(value);
|
|
19498
|
+
if (!record) return;
|
|
19499
|
+
seen.add(value);
|
|
19500
|
+
collectReferencesFromRecord(record, refs);
|
|
19501
|
+
for (const key of UI_CONTAINER_KEYS) {
|
|
19502
|
+
const nested = asRecord2(record[key]);
|
|
19503
|
+
if (nested) collectReferencesFromRecord(nested, refs);
|
|
19504
|
+
}
|
|
19505
|
+
for (const nested of Object.values(record).slice(0, 24)) {
|
|
19506
|
+
scanForHeapReferences(nested, heap, refs, depth + 1, seen);
|
|
19507
|
+
}
|
|
19508
|
+
}
|
|
19509
|
+
function resolveVariablesToReferences(variableNames, heap, refs) {
|
|
19510
|
+
for (const variableName of variableNames) {
|
|
19511
|
+
const variable = heap.variablesByName?.[variableName];
|
|
19512
|
+
if (!variable) continue;
|
|
19513
|
+
if (variable.kind === "entry" && variable.entryPath) {
|
|
19514
|
+
refs.entryPaths.add(variable.entryPath);
|
|
19515
|
+
}
|
|
19516
|
+
if (variable.kind === "list" && variable.listName) {
|
|
19517
|
+
refs.listNames.add(variable.listName);
|
|
19518
|
+
}
|
|
19519
|
+
}
|
|
19520
|
+
}
|
|
19521
|
+
function sortEntries(entries) {
|
|
19522
|
+
return [...entries].sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));
|
|
19523
|
+
}
|
|
19524
|
+
function sortLists(lists) {
|
|
19525
|
+
return [...lists].sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));
|
|
19526
|
+
}
|
|
19527
|
+
function dedupeEntries(entries) {
|
|
19528
|
+
const seen = /* @__PURE__ */ new Set();
|
|
19529
|
+
const result = [];
|
|
19530
|
+
for (const entry of entries) {
|
|
19531
|
+
if (!entry?.path || seen.has(entry.path)) continue;
|
|
19532
|
+
seen.add(entry.path);
|
|
19533
|
+
result.push(entry);
|
|
19534
|
+
}
|
|
19535
|
+
return result;
|
|
19536
|
+
}
|
|
19537
|
+
function dedupeLists(lists) {
|
|
19538
|
+
const seen = /* @__PURE__ */ new Set();
|
|
19539
|
+
const result = [];
|
|
19540
|
+
for (const list of lists) {
|
|
19541
|
+
if (!list?.name || seen.has(list.name)) continue;
|
|
19542
|
+
seen.add(list.name);
|
|
19543
|
+
result.push(list);
|
|
19544
|
+
}
|
|
19545
|
+
return result;
|
|
19546
|
+
}
|
|
19547
|
+
function extractResponseText(result, stdout) {
|
|
19548
|
+
const directText = normalizeText(result);
|
|
19549
|
+
if (directText) return directText;
|
|
19550
|
+
const record = asRecord2(result);
|
|
19551
|
+
if (record) {
|
|
19552
|
+
for (const key of RESPONSE_KEYS) {
|
|
19553
|
+
const normalized = normalizeText(record[key]);
|
|
19554
|
+
if (normalized) return normalized;
|
|
19555
|
+
}
|
|
19556
|
+
for (const containerKey of UI_CONTAINER_KEYS) {
|
|
19557
|
+
const nested = asRecord2(record[containerKey]);
|
|
19558
|
+
if (!nested) continue;
|
|
19559
|
+
for (const key of RESPONSE_KEYS) {
|
|
19560
|
+
const normalized = normalizeText(nested[key]);
|
|
19561
|
+
if (normalized) return normalized;
|
|
19562
|
+
}
|
|
19563
|
+
}
|
|
19564
|
+
}
|
|
19565
|
+
return humanTextFromStdout(stdout);
|
|
19566
|
+
}
|
|
19567
|
+
function fallbackResponseText(entries, lists) {
|
|
19568
|
+
if (entries.length > 0) {
|
|
19569
|
+
return entries.length === 1 ? "I found one relevant record." : `I found ${entries.length} relevant records.`;
|
|
19570
|
+
}
|
|
19571
|
+
if (lists.length > 0) {
|
|
19572
|
+
const emptyOnly = lists.every((list) => (list.paths || []).length === 0);
|
|
19573
|
+
if (emptyOnly) {
|
|
19574
|
+
return lists.length === 1 ? "I saved one empty result set." : `I saved ${lists.length} empty result sets.`;
|
|
19575
|
+
}
|
|
19576
|
+
return lists.length === 1 ? "I saved one result set." : `I saved ${lists.length} result sets.`;
|
|
19577
|
+
}
|
|
19578
|
+
return null;
|
|
19579
|
+
}
|
|
19580
|
+
function getJobRelatedEntries(heap, jobId) {
|
|
19581
|
+
return sortEntries(
|
|
19582
|
+
Object.values(heap.entriesByPath || {}).filter(
|
|
19583
|
+
(entry) => entry.relatedJobIds?.includes(jobId)
|
|
19584
|
+
)
|
|
19585
|
+
);
|
|
19586
|
+
}
|
|
19587
|
+
function getJobRelatedLists(heap, jobId) {
|
|
19588
|
+
return sortLists(
|
|
19589
|
+
Object.values(heap.listsByName || {}).filter(
|
|
19590
|
+
(list) => list.relatedJobIds?.includes(jobId)
|
|
19591
|
+
)
|
|
19592
|
+
);
|
|
19593
|
+
}
|
|
19594
|
+
function entriesFromLists(lists, heap) {
|
|
19595
|
+
const entries = [];
|
|
19596
|
+
for (const list of lists) {
|
|
19597
|
+
for (const path6 of list.paths || []) {
|
|
19598
|
+
const entry = heap.entriesByPath?.[path6];
|
|
19599
|
+
if (entry) entries.push(entry);
|
|
19600
|
+
}
|
|
19601
|
+
}
|
|
19602
|
+
return entries;
|
|
19603
|
+
}
|
|
19604
|
+
function resolveJobPresentation({
|
|
19605
|
+
jobId,
|
|
19606
|
+
result,
|
|
19607
|
+
stdout = [],
|
|
19608
|
+
sessionHeap,
|
|
19609
|
+
allowExplicitArtifacts = true
|
|
19610
|
+
}) {
|
|
19611
|
+
const refs = {
|
|
19612
|
+
entryPaths: /* @__PURE__ */ new Set(),
|
|
19613
|
+
listNames: /* @__PURE__ */ new Set(),
|
|
19614
|
+
variableNames: /* @__PURE__ */ new Set()
|
|
19615
|
+
};
|
|
19616
|
+
if (allowExplicitArtifacts) {
|
|
19617
|
+
scanForHeapReferences(result, sessionHeap, refs);
|
|
19618
|
+
resolveVariablesToReferences(refs.variableNames, sessionHeap, refs);
|
|
19619
|
+
}
|
|
19620
|
+
const referencedLists = sortLists(
|
|
19621
|
+
[...refs.listNames].map((name) => sessionHeap.listsByName?.[name]).filter((list) => Boolean(list))
|
|
19622
|
+
);
|
|
19623
|
+
const referencedEntries = sortEntries(
|
|
19624
|
+
[...refs.entryPaths].map((path6) => sessionHeap.entriesByPath?.[path6]).filter((entry) => Boolean(entry))
|
|
19625
|
+
);
|
|
19626
|
+
const jobLists = getJobRelatedLists(sessionHeap, jobId);
|
|
19627
|
+
const jobEntries = getJobRelatedEntries(sessionHeap, jobId);
|
|
19628
|
+
const changedEntries = dedupeEntries([
|
|
19629
|
+
...jobEntries,
|
|
19630
|
+
...entriesFromLists(jobLists, sessionHeap)
|
|
19631
|
+
]);
|
|
19632
|
+
const explicitLists = dedupeLists(referencedLists);
|
|
19633
|
+
const explicitEntries = dedupeEntries([
|
|
19634
|
+
...referencedEntries,
|
|
19635
|
+
...entriesFromLists(referencedLists, sessionHeap)
|
|
19636
|
+
]);
|
|
19637
|
+
const hasExplicitArtifacts = allowExplicitArtifacts && (explicitEntries.length > 0 || explicitLists.length > 0);
|
|
19638
|
+
const lists = hasExplicitArtifacts ? explicitLists : jobLists;
|
|
19639
|
+
const entries = hasExplicitArtifacts ? explicitEntries : changedEntries;
|
|
19640
|
+
const responseText = extractResponseText(result, stdout) || fallbackResponseText(entries, lists);
|
|
19641
|
+
return {
|
|
19642
|
+
responseText,
|
|
19643
|
+
entries,
|
|
19644
|
+
lists,
|
|
19645
|
+
changedEntries,
|
|
19646
|
+
changedLists: jobLists,
|
|
19647
|
+
hasExplicitArtifacts
|
|
19648
|
+
};
|
|
19649
|
+
}
|
|
19650
|
+
|
|
19651
|
+
// src/session-transcript.ts
|
|
19652
|
+
var EMPTY_HEAP = {
|
|
19653
|
+
entriesByPath: {},
|
|
19654
|
+
listsByName: {},
|
|
19655
|
+
variablesByName: {}};
|
|
19656
|
+
function asRecord3(value) {
|
|
19657
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
19658
|
+
return value;
|
|
19659
|
+
}
|
|
19660
|
+
function asArray(value) {
|
|
19661
|
+
return Array.isArray(value) ? value : [];
|
|
19662
|
+
}
|
|
19663
|
+
function asNumber(value) {
|
|
19664
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
19665
|
+
}
|
|
19666
|
+
function asString(value) {
|
|
19667
|
+
return typeof value === "string" ? value : void 0;
|
|
19668
|
+
}
|
|
19669
|
+
function trimString(value) {
|
|
19670
|
+
return typeof value === "string" ? value.trim() : "";
|
|
19671
|
+
}
|
|
19672
|
+
function normalizeShowRefs(value) {
|
|
19673
|
+
const record = asRecord3(value);
|
|
19674
|
+
if (!record) return void 0;
|
|
19675
|
+
const normalizeRefs = (input) => {
|
|
19676
|
+
if (!Array.isArray(input)) return void 0;
|
|
19677
|
+
const refs = Array.from(
|
|
19678
|
+
new Set(
|
|
19679
|
+
input.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean)
|
|
19680
|
+
)
|
|
19681
|
+
);
|
|
19682
|
+
return refs.length > 0 ? refs : void 0;
|
|
19683
|
+
};
|
|
19684
|
+
const show = {
|
|
19685
|
+
entryPaths: normalizeRefs(record.entryPaths),
|
|
19686
|
+
listNames: normalizeRefs(record.listNames),
|
|
19687
|
+
variableNames: normalizeRefs(record.variableNames)
|
|
19688
|
+
};
|
|
19689
|
+
return show.entryPaths || show.listNames || show.variableNames ? show : void 0;
|
|
19690
|
+
}
|
|
19691
|
+
function stringifyTranscriptValue(value, fallback2 = "") {
|
|
19692
|
+
if (typeof value === "string") {
|
|
19693
|
+
return value.trim() || fallback2;
|
|
19694
|
+
}
|
|
19695
|
+
if (typeof value === "boolean") {
|
|
19696
|
+
return value ? "Confirmed" : "Canceled";
|
|
19697
|
+
}
|
|
19698
|
+
if (value === void 0) {
|
|
19699
|
+
return fallback2;
|
|
19700
|
+
}
|
|
19701
|
+
try {
|
|
19702
|
+
const json = JSON.stringify(value, null, 2);
|
|
19703
|
+
if (!json || json === "undefined") return fallback2;
|
|
19704
|
+
return json.length > 2e3 ? `${json.slice(0, 2e3)}...` : json;
|
|
19705
|
+
} catch {
|
|
19706
|
+
return String(value);
|
|
19707
|
+
}
|
|
19708
|
+
}
|
|
19709
|
+
function buildArtifactHistory(show) {
|
|
19710
|
+
if (!show) return void 0;
|
|
19711
|
+
return `[Agent message]
|
|
19712
|
+
${stringifyTranscriptValue({ show }, "")}`;
|
|
19713
|
+
}
|
|
19714
|
+
function normalizeConversationMessage(raw) {
|
|
19715
|
+
const record = asRecord3(raw);
|
|
19716
|
+
if (!record) return null;
|
|
19717
|
+
const role = record.role === "user" ? "user" : record.role === "assistant" ? "assistant" : null;
|
|
19718
|
+
if (!role) return null;
|
|
19719
|
+
const content = trimString(
|
|
19720
|
+
record.content ?? record.reply ?? record.message ?? record.text
|
|
19721
|
+
);
|
|
19722
|
+
const show = normalizeShowRefs(record.show);
|
|
19723
|
+
const id = asString(record.id) || crypto.randomUUID();
|
|
19724
|
+
const timestamp = asNumber(record.timestamp) || asNumber(record.ts) || 0;
|
|
19725
|
+
if (!content && !show) return null;
|
|
19726
|
+
return {
|
|
19727
|
+
id,
|
|
19728
|
+
role,
|
|
19729
|
+
content,
|
|
19730
|
+
timestamp,
|
|
19731
|
+
jobId: asString(record.jobId),
|
|
19732
|
+
promptId: asString(record.promptId),
|
|
19733
|
+
show,
|
|
19734
|
+
historyContent: role === "assistant" ? content ? `[Assistant reply]
|
|
19735
|
+
${content}` : buildArtifactHistory(show) : void 0,
|
|
19736
|
+
source: "conversation"
|
|
19737
|
+
};
|
|
19738
|
+
}
|
|
19739
|
+
function normalizePromptEntries(jobId, rawPrompts, conversationPromptIds) {
|
|
19740
|
+
const promptsById = asRecord3(rawPrompts) || {};
|
|
19741
|
+
return Object.values(promptsById).map((value) => asRecord3(value)).filter((value) => Boolean(value)).sort(
|
|
19742
|
+
(left, right) => (asNumber(left.openedAt) || asNumber(left.answeredAt) || 0) - (asNumber(right.openedAt) || asNumber(right.answeredAt) || 0)
|
|
19743
|
+
).flatMap((prompt3) => {
|
|
19744
|
+
const promptId = asString(prompt3.promptId);
|
|
19745
|
+
if (!promptId || conversationPromptIds.has(promptId)) return [];
|
|
19746
|
+
const title = trimString(prompt3.title);
|
|
19747
|
+
const message = trimString(prompt3.message);
|
|
19748
|
+
const assistantContent = message || title || "Input required";
|
|
19749
|
+
const openedAt = asNumber(prompt3.openedAt) || 0;
|
|
19750
|
+
const answeredAt = asNumber(prompt3.answeredAt) || openedAt;
|
|
19751
|
+
const entries = [
|
|
19752
|
+
{
|
|
19753
|
+
id: `prompt:${promptId}:assistant`,
|
|
19754
|
+
role: "assistant",
|
|
19755
|
+
content: assistantContent,
|
|
19756
|
+
timestamp: openedAt,
|
|
19757
|
+
jobId,
|
|
19758
|
+
promptId,
|
|
19759
|
+
historyContent: `[Assistant reply]
|
|
19760
|
+
${assistantContent}`,
|
|
19761
|
+
source: "job_prompt"
|
|
19762
|
+
}
|
|
19763
|
+
];
|
|
19764
|
+
if (Object.prototype.hasOwnProperty.call(prompt3, "answer")) {
|
|
19765
|
+
entries.push({
|
|
19766
|
+
id: `prompt:${promptId}:user`,
|
|
19767
|
+
role: "user",
|
|
19768
|
+
content: stringifyTranscriptValue(prompt3.answer, ""),
|
|
19769
|
+
timestamp: answeredAt,
|
|
19770
|
+
jobId,
|
|
19771
|
+
promptId,
|
|
19772
|
+
source: "job_prompt"
|
|
19773
|
+
});
|
|
19774
|
+
}
|
|
19775
|
+
return entries;
|
|
19776
|
+
});
|
|
19777
|
+
}
|
|
19778
|
+
function normalizeAgentMessageEntries(jobId, rawMessages) {
|
|
19779
|
+
return asArray(rawMessages).map((value) => asRecord3(value)).filter((value) => Boolean(value)).sort(
|
|
19780
|
+
(left, right) => (asNumber(left.timestamp) || asNumber(left.ts) || 0) - (asNumber(right.timestamp) || asNumber(right.ts) || 0)
|
|
19781
|
+
).flatMap((message) => {
|
|
19782
|
+
const messageId = asString(message.messageId) || asString(message.id) || crypto.randomUUID();
|
|
19783
|
+
const timestamp = asNumber(message.timestamp) || asNumber(message.ts) || 0;
|
|
19784
|
+
const reply = trimString(
|
|
19785
|
+
message.reply ?? message.message ?? message.text ?? message.content
|
|
19786
|
+
);
|
|
19787
|
+
const show = normalizeShowRefs(message.show);
|
|
19788
|
+
const entries = [];
|
|
19789
|
+
if (reply) {
|
|
19790
|
+
entries.push({
|
|
19791
|
+
id: `agent:${messageId}:text`,
|
|
19792
|
+
role: "assistant",
|
|
19793
|
+
content: reply,
|
|
19794
|
+
timestamp,
|
|
19795
|
+
jobId,
|
|
19796
|
+
historyContent: `[Assistant reply]
|
|
19797
|
+
${reply}`,
|
|
19798
|
+
source: "job_agent_message"
|
|
19799
|
+
});
|
|
19800
|
+
}
|
|
19801
|
+
if (show) {
|
|
19802
|
+
entries.push({
|
|
19803
|
+
id: `agent:${messageId}:artifacts`,
|
|
19804
|
+
role: "assistant",
|
|
19805
|
+
content: "",
|
|
19806
|
+
timestamp,
|
|
19807
|
+
jobId,
|
|
19808
|
+
show,
|
|
19809
|
+
historyContent: buildArtifactHistory(show),
|
|
19810
|
+
source: "job_agent_message"
|
|
19811
|
+
});
|
|
19812
|
+
}
|
|
19813
|
+
return entries;
|
|
19814
|
+
});
|
|
19815
|
+
}
|
|
19816
|
+
function buildJobFallbackEntries(jobId, job2, sessionHeap) {
|
|
19817
|
+
const timestamp = asNumber(job2.finishedAt) || asNumber(job2.startedAt) || asNumber(job2.submittedAt) || 0;
|
|
19818
|
+
const resultPreview = stringifyTranscriptValue(
|
|
19819
|
+
job2.result,
|
|
19820
|
+
"No job result recorded."
|
|
19821
|
+
);
|
|
19822
|
+
const presentation = resolveJobPresentation({
|
|
19823
|
+
jobId,
|
|
19824
|
+
result: job2.result,
|
|
19825
|
+
stdout: [],
|
|
19826
|
+
sessionHeap
|
|
19827
|
+
});
|
|
19828
|
+
const entries = [];
|
|
19829
|
+
const responseText = presentation.responseText || "";
|
|
19830
|
+
if (responseText) {
|
|
19831
|
+
entries.push({
|
|
19832
|
+
id: `job:${jobId}:result-text`,
|
|
19833
|
+
role: "assistant",
|
|
19834
|
+
content: responseText,
|
|
19835
|
+
timestamp,
|
|
19836
|
+
jobId,
|
|
19837
|
+
historyContent: `[Assistant reply]
|
|
19838
|
+
${responseText}`,
|
|
19839
|
+
source: "job_result"
|
|
19840
|
+
});
|
|
19841
|
+
}
|
|
19842
|
+
const show = {
|
|
19843
|
+
entryPaths: presentation.entries.map((entry) => entry.path),
|
|
19844
|
+
listNames: presentation.lists.map((list) => list.name)
|
|
19845
|
+
};
|
|
19846
|
+
if (show.entryPaths && show.entryPaths.length > 0 || show.listNames && show.listNames.length > 0) {
|
|
19847
|
+
entries.push({
|
|
19848
|
+
id: `job:${jobId}:result-artifacts`,
|
|
19849
|
+
role: "assistant",
|
|
19850
|
+
content: "",
|
|
19851
|
+
timestamp,
|
|
19852
|
+
jobId,
|
|
19853
|
+
show,
|
|
19854
|
+
historyContent: buildArtifactHistory(show),
|
|
19855
|
+
source: "job_result"
|
|
19856
|
+
});
|
|
19857
|
+
}
|
|
19858
|
+
if (entries.length === 0 && trimString(job2.error)) {
|
|
19859
|
+
entries.push({
|
|
19860
|
+
id: `job:${jobId}:result-error`,
|
|
19861
|
+
role: "assistant",
|
|
19862
|
+
content: trimString(job2.error),
|
|
19863
|
+
timestamp,
|
|
19864
|
+
jobId,
|
|
19865
|
+
historyContent: `[Assistant reply]
|
|
19866
|
+
${trimString(job2.error)}`,
|
|
19867
|
+
source: "job_result"
|
|
19868
|
+
});
|
|
19869
|
+
}
|
|
19870
|
+
if (entries.length === 0 && resultPreview && resultPreview !== "No job result recorded.") {
|
|
19871
|
+
entries.push({
|
|
19872
|
+
id: `job:${jobId}:result-preview`,
|
|
19873
|
+
role: "assistant",
|
|
19874
|
+
content: resultPreview,
|
|
19875
|
+
timestamp,
|
|
19876
|
+
jobId,
|
|
19877
|
+
historyContent: `[Assistant reply]
|
|
19878
|
+
${resultPreview}`,
|
|
19879
|
+
source: "job_result"
|
|
19880
|
+
});
|
|
19881
|
+
}
|
|
19882
|
+
return entries;
|
|
19883
|
+
}
|
|
19884
|
+
function buildJobCodeEntry(jobId, job2) {
|
|
19885
|
+
const code = trimString(job2.source);
|
|
19886
|
+
if (!code) return null;
|
|
19887
|
+
const jobStatus = asString(job2.status);
|
|
19888
|
+
const error2 = jobStatus === "failed" || jobStatus === "canceled" || jobStatus === "timeout" ? trimString(job2.error) || `Job ${jobStatus}` : void 0;
|
|
19889
|
+
return {
|
|
19890
|
+
id: `job:${jobId}:code`,
|
|
19891
|
+
role: "assistant",
|
|
19892
|
+
content: "",
|
|
19893
|
+
timestamp: asNumber(job2.submittedAt) || asNumber(job2.startedAt) || asNumber(job2.finishedAt) || 0,
|
|
19894
|
+
jobId,
|
|
19895
|
+
code,
|
|
19896
|
+
jobStatus,
|
|
19897
|
+
jobResultPreview: stringifyTranscriptValue(job2.result, "No job result recorded."),
|
|
19898
|
+
error: error2,
|
|
19899
|
+
source: "job_code"
|
|
19900
|
+
};
|
|
19901
|
+
}
|
|
19902
|
+
function buildSessionTranscript(input) {
|
|
19903
|
+
const liveDoc = input.liveDoc || null;
|
|
19904
|
+
const sessionHeap = input.sessionHeap || EMPTY_HEAP;
|
|
19905
|
+
const transcript = [];
|
|
19906
|
+
const conversationMessages = asArray(asRecord3(liveDoc?.conversation)?.messages).map((message) => normalizeConversationMessage(message)).filter((message) => Boolean(message));
|
|
19907
|
+
const conversationPromptIds = new Set(
|
|
19908
|
+
conversationMessages.map((message) => message.promptId).filter((promptId) => Boolean(promptId))
|
|
19909
|
+
);
|
|
19910
|
+
const assistantConversationJobIds = new Set(
|
|
19911
|
+
conversationMessages.filter((message) => message.role === "assistant" && Boolean(message.jobId)).map((message) => message.jobId)
|
|
19912
|
+
);
|
|
19913
|
+
transcript.push(...conversationMessages);
|
|
19914
|
+
const jobsById = asRecord3(asRecord3(liveDoc?.jobs)?.byId) || {};
|
|
19915
|
+
const jobs = Object.values(jobsById).map((value) => asRecord3(value)).filter((value) => Boolean(value)).sort(
|
|
19916
|
+
(left, right) => (asNumber(left.submittedAt) || asNumber(left.startedAt) || asNumber(left.finishedAt) || 0) - (asNumber(right.submittedAt) || asNumber(right.startedAt) || asNumber(right.finishedAt) || 0)
|
|
19917
|
+
);
|
|
19918
|
+
for (const job2 of jobs) {
|
|
19919
|
+
const jobId = asString(job2.jobId);
|
|
19920
|
+
if (!jobId) continue;
|
|
19921
|
+
const codeEntry = buildJobCodeEntry(jobId, job2);
|
|
19922
|
+
if (codeEntry) {
|
|
19923
|
+
transcript.push(codeEntry);
|
|
19924
|
+
}
|
|
19925
|
+
transcript.push(
|
|
19926
|
+
...normalizePromptEntries(jobId, job2.prompts, conversationPromptIds)
|
|
19927
|
+
);
|
|
19928
|
+
if (!assistantConversationJobIds.has(jobId)) {
|
|
19929
|
+
const agentEntries = normalizeAgentMessageEntries(jobId, job2.agentMessages);
|
|
19930
|
+
if (agentEntries.length > 0) {
|
|
19931
|
+
transcript.push(...agentEntries);
|
|
19932
|
+
} else {
|
|
19933
|
+
transcript.push(
|
|
19934
|
+
...buildJobFallbackEntries(
|
|
19935
|
+
jobId,
|
|
19936
|
+
job2,
|
|
19937
|
+
sessionHeap
|
|
19938
|
+
)
|
|
19939
|
+
);
|
|
19940
|
+
}
|
|
19941
|
+
}
|
|
19942
|
+
}
|
|
19943
|
+
return transcript.sort((left, right) => {
|
|
19944
|
+
if (left.timestamp !== right.timestamp) {
|
|
19945
|
+
return left.timestamp - right.timestamp;
|
|
19946
|
+
}
|
|
19947
|
+
return left.id.localeCompare(right.id);
|
|
19948
|
+
});
|
|
19949
|
+
}
|
|
19950
|
+
|
|
19401
19951
|
// src/effect-runtime.ts
|
|
19402
19952
|
function computeEffectKey(effect) {
|
|
19403
19953
|
const attachedClass = effect.className?.trim();
|
|
@@ -20015,7 +20565,9 @@ var Environment = class {
|
|
|
20015
20565
|
}
|
|
20016
20566
|
);
|
|
20017
20567
|
if (result.errors?.length) {
|
|
20018
|
-
throw new Error(
|
|
20568
|
+
throw new Error(
|
|
20569
|
+
`defineRelationship failed: ${result.errors[0]?.message ?? "Unknown GraphQL error"}`
|
|
20570
|
+
);
|
|
20019
20571
|
}
|
|
20020
20572
|
return result.data.at.define_relationship;
|
|
20021
20573
|
}
|
|
@@ -20051,7 +20603,9 @@ var Environment = class {
|
|
|
20051
20603
|
{ path: modelPath }
|
|
20052
20604
|
);
|
|
20053
20605
|
if (result.errors?.length) {
|
|
20054
|
-
throw new Error(
|
|
20606
|
+
throw new Error(
|
|
20607
|
+
`getRelationships failed: ${result.errors[0]?.message ?? "Unknown GraphQL error"}`
|
|
20608
|
+
);
|
|
20055
20609
|
}
|
|
20056
20610
|
return result.data?.model?.relationships || [];
|
|
20057
20611
|
}
|
|
@@ -20090,7 +20644,9 @@ var Environment = class {
|
|
|
20090
20644
|
{ target: targetPath }
|
|
20091
20645
|
);
|
|
20092
20646
|
if (result.errors?.length) {
|
|
20093
|
-
throw new Error(
|
|
20647
|
+
throw new Error(
|
|
20648
|
+
`attach failed: ${result.errors[0]?.message ?? "Unknown GraphQL error"}`
|
|
20649
|
+
);
|
|
20094
20650
|
}
|
|
20095
20651
|
}
|
|
20096
20652
|
/**
|
|
@@ -20125,7 +20681,9 @@ var Environment = class {
|
|
|
20125
20681
|
}`
|
|
20126
20682
|
);
|
|
20127
20683
|
if (result.errors?.length) {
|
|
20128
|
-
throw new Error(
|
|
20684
|
+
throw new Error(
|
|
20685
|
+
`detach failed: ${result.errors[0]?.message ?? "Unknown GraphQL error"}`
|
|
20686
|
+
);
|
|
20129
20687
|
}
|
|
20130
20688
|
}
|
|
20131
20689
|
/**
|
|
@@ -20152,7 +20710,9 @@ var Environment = class {
|
|
|
20152
20710
|
}`
|
|
20153
20711
|
);
|
|
20154
20712
|
if (result.errors?.length) {
|
|
20155
|
-
throw new Error(
|
|
20713
|
+
throw new Error(
|
|
20714
|
+
`listRelated failed: ${result.errors[0]?.message ?? "Unknown GraphQL error"}`
|
|
20715
|
+
);
|
|
20156
20716
|
}
|
|
20157
20717
|
return result.data?.at?.at?.list_related || [];
|
|
20158
20718
|
}
|
|
@@ -20245,7 +20805,9 @@ var Environment = class {
|
|
|
20245
20805
|
async _runGraphql(query, label) {
|
|
20246
20806
|
const result = await this.graphql(query);
|
|
20247
20807
|
if (result.errors?.length) {
|
|
20248
|
-
throw new Error(
|
|
20808
|
+
throw new Error(
|
|
20809
|
+
`${label}: ${result.errors[0]?.message ?? "Unknown GraphQL error"}`
|
|
20810
|
+
);
|
|
20249
20811
|
}
|
|
20250
20812
|
return result.data;
|
|
20251
20813
|
}
|
|
@@ -20590,7 +21152,11 @@ var Environment = class {
|
|
|
20590
21152
|
*/
|
|
20591
21153
|
async recordObject(options) {
|
|
20592
21154
|
const results = await this.recordObjects([options]);
|
|
20593
|
-
|
|
21155
|
+
const result = results[0];
|
|
21156
|
+
if (!result) {
|
|
21157
|
+
throw new Error("recordObject: no result returned for record");
|
|
21158
|
+
}
|
|
21159
|
+
return result;
|
|
20594
21160
|
}
|
|
20595
21161
|
/**
|
|
20596
21162
|
* Batch version of `recordObject()`.
|
|
@@ -20642,7 +21208,13 @@ var Environment = class {
|
|
|
20642
21208
|
);
|
|
20643
21209
|
}
|
|
20644
21210
|
for (let index = 0; index < items.length; index += 1) {
|
|
20645
|
-
|
|
21211
|
+
const item = items[index];
|
|
21212
|
+
if (!item) {
|
|
21213
|
+
throw new Error(
|
|
21214
|
+
`recordObjects: chunk ${plan.chunkIndex + 1} returned an empty result at index ${index}`
|
|
21215
|
+
);
|
|
21216
|
+
}
|
|
21217
|
+
results[plan.offset + index] = item;
|
|
20646
21218
|
}
|
|
20647
21219
|
if (onChunk) {
|
|
20648
21220
|
const info2 = {
|
|
@@ -20770,6 +21342,9 @@ var EnvironmentSession = class extends Session {
|
|
|
20770
21342
|
get envName() {
|
|
20771
21343
|
return this.environment.envName;
|
|
20772
21344
|
}
|
|
21345
|
+
get tag() {
|
|
21346
|
+
return this.environment.tag;
|
|
21347
|
+
}
|
|
20773
21348
|
get versionId() {
|
|
20774
21349
|
return this.environment.versionId;
|
|
20775
21350
|
}
|
|
@@ -20789,12 +21364,171 @@ var EnvironmentSession = class extends Session {
|
|
|
20789
21364
|
return this.environment.feedback;
|
|
20790
21365
|
}
|
|
20791
21366
|
/**
|
|
20792
|
-
* Return a plain JS
|
|
21367
|
+
* Return a plain JS copy of the synced session heap.
|
|
20793
21368
|
*/
|
|
20794
21369
|
getHeap() {
|
|
20795
21370
|
const doc = this.document;
|
|
20796
21371
|
return normalizeHeapSnapshot(doc?.heap);
|
|
20797
21372
|
}
|
|
21373
|
+
async sessionDataRequest(path6, query) {
|
|
21374
|
+
const searchParams = new URLSearchParams();
|
|
21375
|
+
for (const [key, value] of Object.entries(query || {})) {
|
|
21376
|
+
if (value !== null && typeof value !== "undefined" && value !== "") {
|
|
21377
|
+
searchParams.set(key, String(value));
|
|
21378
|
+
}
|
|
21379
|
+
}
|
|
21380
|
+
const queryString = searchParams.toString();
|
|
21381
|
+
const response = await fetch(
|
|
21382
|
+
`${this.environment.runtimeBaseUrl}/orchestrator/ws/sessions/${encodeURIComponent(this.sessionId)}${path6}${queryString ? `?${queryString}` : ""}`,
|
|
21383
|
+
{
|
|
21384
|
+
method: "GET",
|
|
21385
|
+
headers: {
|
|
21386
|
+
Authorization: `Bearer ${this.environment.authToken}`,
|
|
21387
|
+
"Content-Type": "application/json"
|
|
21388
|
+
}
|
|
21389
|
+
}
|
|
21390
|
+
);
|
|
21391
|
+
if (!response.ok) {
|
|
21392
|
+
const errorText = await response.text();
|
|
21393
|
+
throw new Error(
|
|
21394
|
+
`Session data API Error (${response.status}): ${errorText}`
|
|
21395
|
+
);
|
|
21396
|
+
}
|
|
21397
|
+
return response.json();
|
|
21398
|
+
}
|
|
21399
|
+
async collectAllSessionItems(listPage) {
|
|
21400
|
+
const items = [];
|
|
21401
|
+
let cursor = null;
|
|
21402
|
+
do {
|
|
21403
|
+
const page = await listPage({ limit: 500, cursor });
|
|
21404
|
+
items.push(...page.items);
|
|
21405
|
+
cursor = page.nextCursor;
|
|
21406
|
+
} while (cursor);
|
|
21407
|
+
return items;
|
|
21408
|
+
}
|
|
21409
|
+
/**
|
|
21410
|
+
* Fetch the live session document from the runtime DO.
|
|
21411
|
+
*
|
|
21412
|
+
* For history and saved artifacts, prefer the collection APIs on
|
|
21413
|
+
* `messages`, `timeline`, `jobs`, and `heap`.
|
|
21414
|
+
*/
|
|
21415
|
+
async getDocument() {
|
|
21416
|
+
return this.sessionDataRequest("/document");
|
|
21417
|
+
}
|
|
21418
|
+
get messages() {
|
|
21419
|
+
return {
|
|
21420
|
+
list: (options = {}) => this.sessionDataRequest(
|
|
21421
|
+
"/messages",
|
|
21422
|
+
options
|
|
21423
|
+
)
|
|
21424
|
+
};
|
|
21425
|
+
}
|
|
21426
|
+
get timeline() {
|
|
21427
|
+
return {
|
|
21428
|
+
list: (options = {}) => this.sessionDataRequest(
|
|
21429
|
+
"/timeline",
|
|
21430
|
+
options
|
|
21431
|
+
)
|
|
21432
|
+
};
|
|
21433
|
+
}
|
|
21434
|
+
get jobs() {
|
|
21435
|
+
return {
|
|
21436
|
+
list: (options = {}) => this.sessionDataRequest(
|
|
21437
|
+
"/jobs",
|
|
21438
|
+
options
|
|
21439
|
+
),
|
|
21440
|
+
get: (jobId) => this.sessionDataRequest(
|
|
21441
|
+
`/jobs/${encodeURIComponent(jobId)}`
|
|
21442
|
+
)
|
|
21443
|
+
};
|
|
21444
|
+
}
|
|
21445
|
+
get heap() {
|
|
21446
|
+
return {
|
|
21447
|
+
entries: {
|
|
21448
|
+
list: (options = {}) => this.sessionDataRequest(
|
|
21449
|
+
"/heap/entries",
|
|
21450
|
+
options
|
|
21451
|
+
),
|
|
21452
|
+
get: (path6) => this.sessionDataRequest(
|
|
21453
|
+
`/heap/entries/${encodeURIComponent(path6)}`
|
|
21454
|
+
)
|
|
21455
|
+
},
|
|
21456
|
+
lists: {
|
|
21457
|
+
list: (options = {}) => this.sessionDataRequest(
|
|
21458
|
+
"/heap/lists",
|
|
21459
|
+
options
|
|
21460
|
+
),
|
|
21461
|
+
get: (name) => this.sessionDataRequest(
|
|
21462
|
+
`/heap/lists/${encodeURIComponent(name)}`
|
|
21463
|
+
)
|
|
21464
|
+
}
|
|
21465
|
+
};
|
|
21466
|
+
}
|
|
21467
|
+
get transcript() {
|
|
21468
|
+
return {
|
|
21469
|
+
list: async (options = {}) => {
|
|
21470
|
+
const [messages, jobs, entries, lists] = await Promise.all([
|
|
21471
|
+
this.collectAllSessionItems(this.messages.list),
|
|
21472
|
+
this.collectAllSessionItems(
|
|
21473
|
+
(pageOptions) => this.jobs.list({ ...pageOptions, status: "all" })
|
|
21474
|
+
),
|
|
21475
|
+
this.collectAllSessionItems(this.heap.entries.list),
|
|
21476
|
+
this.collectAllSessionItems(this.heap.lists.list)
|
|
21477
|
+
]);
|
|
21478
|
+
const liveDoc = {
|
|
21479
|
+
conversation: { messages },
|
|
21480
|
+
jobs: {
|
|
21481
|
+
byId: Object.fromEntries(
|
|
21482
|
+
jobs.map((job2) => {
|
|
21483
|
+
const record = job2 && typeof job2 === "object" ? job2 : null;
|
|
21484
|
+
const id = typeof record?.jobId === "string" ? record.jobId : typeof record?.id === "string" ? record.id : null;
|
|
21485
|
+
return id ? [id, record] : null;
|
|
21486
|
+
}).filter(
|
|
21487
|
+
(entry) => Boolean(entry)
|
|
21488
|
+
)
|
|
21489
|
+
)
|
|
21490
|
+
}
|
|
21491
|
+
};
|
|
21492
|
+
const heap = normalizeHeapSnapshot({
|
|
21493
|
+
entriesByPath: Object.fromEntries(
|
|
21494
|
+
entries.map((entry) => {
|
|
21495
|
+
return entry?.path ? [
|
|
21496
|
+
entry.path,
|
|
21497
|
+
entry
|
|
21498
|
+
] : null;
|
|
21499
|
+
}).filter(
|
|
21500
|
+
(entry) => Boolean(entry)
|
|
21501
|
+
)
|
|
21502
|
+
),
|
|
21503
|
+
listsByName: Object.fromEntries(
|
|
21504
|
+
lists.map((list) => {
|
|
21505
|
+
return list?.name ? [list.name, list] : null;
|
|
21506
|
+
}).filter(
|
|
21507
|
+
(entry) => Boolean(entry)
|
|
21508
|
+
)
|
|
21509
|
+
),
|
|
21510
|
+
variablesByName: this.getHeap().variablesByName,
|
|
21511
|
+
updatedAt: Date.now()
|
|
21512
|
+
});
|
|
21513
|
+
const allItems = buildSessionTranscript({
|
|
21514
|
+
liveDoc,
|
|
21515
|
+
sessionHeap: heap
|
|
21516
|
+
});
|
|
21517
|
+
const limit = Math.max(
|
|
21518
|
+
1,
|
|
21519
|
+
Math.min(500, Math.floor(options.limit ?? 100))
|
|
21520
|
+
);
|
|
21521
|
+
const offset = typeof options.cursor === "string" ? Number.parseInt(options.cursor, 10) || 0 : 0;
|
|
21522
|
+
const items = allItems.slice(offset, offset + limit);
|
|
21523
|
+
const nextOffset = offset + items.length;
|
|
21524
|
+
return {
|
|
21525
|
+
items,
|
|
21526
|
+
nextCursor: nextOffset < allItems.length ? String(nextOffset) : null,
|
|
21527
|
+
totalCount: allItems.length
|
|
21528
|
+
};
|
|
21529
|
+
}
|
|
21530
|
+
};
|
|
21531
|
+
}
|
|
20798
21532
|
async graphql(query, variables) {
|
|
20799
21533
|
return this.environment.graphql(query, variables);
|
|
20800
21534
|
}
|
|
@@ -22022,14 +22756,18 @@ async function resolveOntologyId(granular, ontology) {
|
|
|
22022
22756
|
const { config } = createGranularClient();
|
|
22023
22757
|
const requestedOntology = ontology ?? config.sandboxId;
|
|
22024
22758
|
if (!requestedOntology) {
|
|
22025
|
-
throw new Error(
|
|
22759
|
+
throw new Error(
|
|
22760
|
+
"No ontology configured. Run `granular init` first or pass `--ontology`."
|
|
22761
|
+
);
|
|
22026
22762
|
}
|
|
22027
22763
|
try {
|
|
22028
22764
|
const sandbox = await granular.sandboxes.get(requestedOntology);
|
|
22029
22765
|
return sandbox.sandboxId;
|
|
22030
22766
|
} catch {
|
|
22031
22767
|
const sandboxes = await granular.sandboxes.list();
|
|
22032
|
-
const existing = sandboxes.items.find(
|
|
22768
|
+
const existing = sandboxes.items.find(
|
|
22769
|
+
(item) => item.name === requestedOntology
|
|
22770
|
+
);
|
|
22033
22771
|
if (existing) {
|
|
22034
22772
|
return existing.sandboxId;
|
|
22035
22773
|
}
|
|
@@ -22037,7 +22775,8 @@ async function resolveOntologyId(granular, ontology) {
|
|
|
22037
22775
|
throw new Error(`Ontology not found: ${requestedOntology}`);
|
|
22038
22776
|
}
|
|
22039
22777
|
function matchesEnvironmentName(environment, requested) {
|
|
22040
|
-
|
|
22778
|
+
const managedPrefix = `__sdk__${requested}__`;
|
|
22779
|
+
return environment.environment === requested || environment.envName === requested || environment.environment?.startsWith(managedPrefix) || environment.envName?.startsWith(managedPrefix) || environment.tag?.name === requested || environment.buildPolicy?.tagName === requested || environment.tracking?.tagName === requested;
|
|
22041
22780
|
}
|
|
22042
22781
|
async function resolveEnvironmentData(granular, options) {
|
|
22043
22782
|
if (options.environmentId) {
|
|
@@ -22046,7 +22785,9 @@ async function resolveEnvironmentData(granular, options) {
|
|
|
22046
22785
|
const ontologyId = await resolveOntologyId(granular, options.ontology);
|
|
22047
22786
|
const environmentName = options.environment ?? "dev";
|
|
22048
22787
|
const environments = await granular.environments.list(ontologyId);
|
|
22049
|
-
const existing = environments.find(
|
|
22788
|
+
const existing = environments.find(
|
|
22789
|
+
(environment) => matchesEnvironmentName(environment, environmentName)
|
|
22790
|
+
);
|
|
22050
22791
|
if (existing) {
|
|
22051
22792
|
return existing;
|
|
22052
22793
|
}
|
|
@@ -22055,13 +22796,13 @@ async function resolveEnvironmentData(granular, options) {
|
|
|
22055
22796
|
`No environment named \`${environmentName}\` found for ontology \`${ontologyId}\`. Run \`granular connect test\` or \`granular session create\` first, or pass \`--environment-id\`.`
|
|
22056
22797
|
);
|
|
22057
22798
|
}
|
|
22058
|
-
const
|
|
22799
|
+
const connection = await granular.connect({
|
|
22059
22800
|
ontology: ontologyId,
|
|
22060
|
-
|
|
22801
|
+
environment: environmentName,
|
|
22061
22802
|
userId: options.userId ?? "granular-cli",
|
|
22062
22803
|
permissions: options.permissions ?? ["default"]
|
|
22063
22804
|
});
|
|
22064
|
-
return await granular.environments.get(
|
|
22805
|
+
return await granular.environments.get(connection.environmentId);
|
|
22065
22806
|
}
|
|
22066
22807
|
async function listSessionsForEnvironment(granular, environmentId, status) {
|
|
22067
22808
|
if (status === "all") {
|
|
@@ -22078,30 +22819,34 @@ async function listSessionsForEnvironment(granular, environmentId, status) {
|
|
|
22078
22819
|
async function connectRuntime(options) {
|
|
22079
22820
|
if (options.sessionId) {
|
|
22080
22821
|
const { granular: granular2 } = createGranularClient();
|
|
22081
|
-
const
|
|
22822
|
+
const environment2 = await granular2.connectSession({
|
|
22823
|
+
sessionId: options.sessionId
|
|
22824
|
+
});
|
|
22082
22825
|
return {
|
|
22083
22826
|
granular: granular2,
|
|
22084
|
-
environment:
|
|
22085
|
-
session:
|
|
22086
|
-
ontologyId:
|
|
22827
|
+
environment: environment2,
|
|
22828
|
+
session: environment2,
|
|
22829
|
+
ontologyId: environment2.ontologyId || environment2.sandboxId
|
|
22087
22830
|
};
|
|
22088
22831
|
}
|
|
22089
22832
|
const { granular, config } = createGranularClient();
|
|
22090
22833
|
const ontologyId = options.ontology ?? config.sandboxId;
|
|
22091
22834
|
if (!ontologyId) {
|
|
22092
|
-
throw new Error(
|
|
22835
|
+
throw new Error(
|
|
22836
|
+
"No ontology configured. Run `granular init` first or pass `--ontology`."
|
|
22837
|
+
);
|
|
22093
22838
|
}
|
|
22094
|
-
const
|
|
22839
|
+
const environmentHandle = await granular.connect({
|
|
22095
22840
|
ontology: ontologyId,
|
|
22096
|
-
|
|
22841
|
+
environment: options.environment ?? "dev",
|
|
22097
22842
|
userId: options.userId ?? "granular-cli",
|
|
22098
22843
|
permissions: options.permissions ?? ["default"]
|
|
22099
22844
|
});
|
|
22100
|
-
const
|
|
22845
|
+
const environment = await environmentHandle.createSession();
|
|
22101
22846
|
return {
|
|
22102
22847
|
granular,
|
|
22103
22848
|
environment,
|
|
22104
|
-
session:
|
|
22849
|
+
session: environment,
|
|
22105
22850
|
ontologyId
|
|
22106
22851
|
};
|
|
22107
22852
|
}
|
|
@@ -22111,9 +22856,9 @@ async function withRuntimeConnection(options, callback) {
|
|
|
22111
22856
|
return await callback(connection);
|
|
22112
22857
|
} finally {
|
|
22113
22858
|
try {
|
|
22114
|
-
await connection.
|
|
22859
|
+
await connection.environment.disconnect();
|
|
22115
22860
|
} catch {
|
|
22116
|
-
connection.
|
|
22861
|
+
connection.environment?.client?.disconnect?.();
|
|
22117
22862
|
}
|
|
22118
22863
|
}
|
|
22119
22864
|
}
|
|
@@ -22140,24 +22885,25 @@ function readJobCodeFromOptions(options) {
|
|
|
22140
22885
|
// src/cli/commands/connect.ts
|
|
22141
22886
|
async function connectTestCommand(options) {
|
|
22142
22887
|
const emitJson = options.json === true;
|
|
22888
|
+
const requestedEnvironment = options.environment ?? "dev";
|
|
22143
22889
|
if (!emitJson) {
|
|
22144
22890
|
printHeader();
|
|
22145
22891
|
}
|
|
22146
22892
|
await withRuntimeConnection(
|
|
22147
22893
|
{
|
|
22148
22894
|
ontology: options.ontology,
|
|
22149
|
-
environment:
|
|
22895
|
+
environment: requestedEnvironment,
|
|
22150
22896
|
userId: options.user,
|
|
22151
22897
|
permissions: normalizePermissions(options.permissions)
|
|
22152
22898
|
},
|
|
22153
|
-
async ({ environment,
|
|
22899
|
+
async ({ environment, ontologyId }) => {
|
|
22154
22900
|
const payload = {
|
|
22155
22901
|
ok: true,
|
|
22156
22902
|
ontologyId,
|
|
22157
22903
|
sandboxId: environment.sandboxId,
|
|
22158
22904
|
environmentId: environment.environmentId,
|
|
22159
|
-
environment: environment.
|
|
22160
|
-
sessionId:
|
|
22905
|
+
environment: environment.tag || requestedEnvironment,
|
|
22906
|
+
sessionId: environment.sessionId,
|
|
22161
22907
|
subjectId: environment.subjectId,
|
|
22162
22908
|
versionId: environment.versionId
|
|
22163
22909
|
};
|
|
@@ -22169,7 +22915,7 @@ async function connectTestCommand(options) {
|
|
|
22169
22915
|
console.log();
|
|
22170
22916
|
keyValue({
|
|
22171
22917
|
"Ontology ID": payload.ontologyId,
|
|
22172
|
-
|
|
22918
|
+
Environment: payload.environment,
|
|
22173
22919
|
"Environment ID": payload.environmentId,
|
|
22174
22920
|
"Session ID": payload.sessionId,
|
|
22175
22921
|
"Subject ID": payload.subjectId,
|
|
@@ -22203,12 +22949,12 @@ async function sessionHeapCommand(options) {
|
|
|
22203
22949
|
permissions: normalizePermissions(options.permissions),
|
|
22204
22950
|
sessionId: options.session
|
|
22205
22951
|
},
|
|
22206
|
-
async ({ environment,
|
|
22952
|
+
async ({ environment, ontologyId }) => {
|
|
22207
22953
|
const payload = {
|
|
22208
22954
|
ontologyId,
|
|
22209
|
-
sessionId:
|
|
22955
|
+
sessionId: environment.sessionId,
|
|
22210
22956
|
environmentId: environment.environmentId,
|
|
22211
|
-
heap:
|
|
22957
|
+
heap: environment.getHeap()
|
|
22212
22958
|
};
|
|
22213
22959
|
if (!emitJson) {
|
|
22214
22960
|
step("Session heap");
|
|
@@ -22231,12 +22977,14 @@ async function sessionDocCommand(options) {
|
|
|
22231
22977
|
permissions: normalizePermissions(options.permissions),
|
|
22232
22978
|
sessionId: options.session
|
|
22233
22979
|
},
|
|
22234
|
-
async ({ environment,
|
|
22980
|
+
async ({ environment, ontologyId }) => {
|
|
22235
22981
|
const payload = {
|
|
22236
22982
|
ontologyId,
|
|
22237
|
-
sessionId:
|
|
22983
|
+
sessionId: environment.sessionId,
|
|
22238
22984
|
environmentId: environment.environmentId,
|
|
22239
|
-
document: documentToJson(
|
|
22985
|
+
document: documentToJson(
|
|
22986
|
+
environment.document
|
|
22987
|
+
)
|
|
22240
22988
|
};
|
|
22241
22989
|
if (!emitJson) {
|
|
22242
22990
|
step("Session document");
|
|
@@ -22248,6 +22996,7 @@ async function sessionDocCommand(options) {
|
|
|
22248
22996
|
}
|
|
22249
22997
|
async function sessionCreateCommand(options) {
|
|
22250
22998
|
const emitJson = options.json === true;
|
|
22999
|
+
const requestedEnvironment = options.environment ?? "dev";
|
|
22251
23000
|
if (!emitJson) {
|
|
22252
23001
|
printHeader();
|
|
22253
23002
|
}
|
|
@@ -22255,24 +23004,24 @@ async function sessionCreateCommand(options) {
|
|
|
22255
23004
|
const permissions = normalizePermissions(options.permissions);
|
|
22256
23005
|
const envData = await resolveEnvironmentData(granular, {
|
|
22257
23006
|
ontology: options.ontology,
|
|
22258
|
-
environment:
|
|
23007
|
+
environment: requestedEnvironment,
|
|
22259
23008
|
environmentId: options.environmentId,
|
|
22260
23009
|
userId: options.user,
|
|
22261
23010
|
permissions,
|
|
22262
23011
|
createIfMissing: true
|
|
22263
23012
|
});
|
|
22264
|
-
const
|
|
23013
|
+
const environment = await granular.createSession({
|
|
22265
23014
|
environmentId: envData.environmentId
|
|
22266
23015
|
});
|
|
22267
23016
|
try {
|
|
22268
23017
|
const payload = {
|
|
22269
23018
|
ok: true,
|
|
22270
23019
|
ontologyId: envData.sandboxId,
|
|
22271
|
-
environmentId:
|
|
22272
|
-
environment:
|
|
22273
|
-
sessionId:
|
|
22274
|
-
subjectId:
|
|
22275
|
-
versionId:
|
|
23020
|
+
environmentId: environment.environmentId,
|
|
23021
|
+
environment: environment.tag || envData.tag?.name || envData.buildPolicy.tagName || requestedEnvironment,
|
|
23022
|
+
sessionId: environment.sessionId,
|
|
23023
|
+
subjectId: environment.subjectId,
|
|
23024
|
+
versionId: environment.versionId
|
|
22276
23025
|
};
|
|
22277
23026
|
if (emitJson) {
|
|
22278
23027
|
console.log(JSON.stringify(payload, null, 2));
|
|
@@ -22282,7 +23031,7 @@ async function sessionCreateCommand(options) {
|
|
|
22282
23031
|
console.log();
|
|
22283
23032
|
keyValue({
|
|
22284
23033
|
"Ontology ID": payload.ontologyId,
|
|
22285
|
-
|
|
23034
|
+
Environment: payload.environment,
|
|
22286
23035
|
"Environment ID": payload.environmentId,
|
|
22287
23036
|
"Session ID": payload.sessionId,
|
|
22288
23037
|
"Subject ID": payload.subjectId,
|
|
@@ -22291,30 +23040,35 @@ async function sessionCreateCommand(options) {
|
|
|
22291
23040
|
console.log();
|
|
22292
23041
|
} finally {
|
|
22293
23042
|
try {
|
|
22294
|
-
await
|
|
23043
|
+
await environment.disconnect();
|
|
22295
23044
|
} catch {
|
|
22296
|
-
|
|
23045
|
+
environment?.client?.disconnect?.();
|
|
22297
23046
|
}
|
|
22298
23047
|
}
|
|
22299
23048
|
}
|
|
22300
23049
|
async function sessionListCommand(options) {
|
|
22301
23050
|
const emitJson = options.json === true;
|
|
22302
23051
|
const status = options.status ?? "active";
|
|
23052
|
+
const requestedEnvironment = options.environment ?? "dev";
|
|
22303
23053
|
if (!emitJson) {
|
|
22304
23054
|
printHeader();
|
|
22305
23055
|
}
|
|
22306
23056
|
const { granular } = createGranularClient();
|
|
22307
23057
|
const environmentData = await resolveEnvironmentData(granular, {
|
|
22308
23058
|
ontology: options.ontology,
|
|
22309
|
-
environment:
|
|
23059
|
+
environment: requestedEnvironment,
|
|
22310
23060
|
environmentId: options.environmentId,
|
|
22311
23061
|
createIfMissing: false
|
|
22312
23062
|
});
|
|
22313
|
-
const items = await listSessionsForEnvironment(
|
|
23063
|
+
const items = await listSessionsForEnvironment(
|
|
23064
|
+
granular,
|
|
23065
|
+
environmentData.environmentId,
|
|
23066
|
+
status
|
|
23067
|
+
);
|
|
22314
23068
|
const payload = {
|
|
22315
23069
|
ontologyId: environmentData.sandboxId,
|
|
22316
23070
|
environmentId: environmentData.environmentId,
|
|
22317
|
-
environment: environmentData.
|
|
23071
|
+
environment: environmentData.tag?.name || environmentData.buildPolicy.tagName || requestedEnvironment,
|
|
22318
23072
|
status,
|
|
22319
23073
|
items
|
|
22320
23074
|
};
|
|
@@ -22418,12 +23172,12 @@ async function effectsListCommand(options) {
|
|
|
22418
23172
|
permissions: normalizePermissions(options.permissions),
|
|
22419
23173
|
sessionId: options.session
|
|
22420
23174
|
},
|
|
22421
|
-
async ({ environment,
|
|
22422
|
-
const effects2 = sortEffects(
|
|
23175
|
+
async ({ environment, ontologyId }) => {
|
|
23176
|
+
const effects2 = sortEffects(environment.getEffects());
|
|
22423
23177
|
const payload = {
|
|
22424
23178
|
ontologyId,
|
|
22425
23179
|
environmentId: environment.environmentId,
|
|
22426
|
-
sessionId:
|
|
23180
|
+
sessionId: environment.sessionId,
|
|
22427
23181
|
items: effects2
|
|
22428
23182
|
};
|
|
22429
23183
|
if (emitJson) {
|
|
@@ -22463,8 +23217,8 @@ async function effectsDiffCommand(options) {
|
|
|
22463
23217
|
permissions: normalizePermissions(options.permissions),
|
|
22464
23218
|
sessionId: options.session
|
|
22465
23219
|
},
|
|
22466
|
-
async ({ environment,
|
|
22467
|
-
const effects2 = sortEffects(
|
|
23220
|
+
async ({ environment, ontologyId }) => {
|
|
23221
|
+
const effects2 = sortEffects(environment.getEffects());
|
|
22468
23222
|
const declared = effects2.map((effect) => effect.name);
|
|
22469
23223
|
const liveReady = effects2.filter((effect) => effect.ready).map((effect) => effect.name);
|
|
22470
23224
|
const declaredOnly = effects2.filter((effect) => !effect.ready).map((effect) => effect.name);
|
|
@@ -22472,7 +23226,7 @@ async function effectsDiffCommand(options) {
|
|
|
22472
23226
|
const payload = {
|
|
22473
23227
|
ontologyId,
|
|
22474
23228
|
environmentId: environment.environmentId,
|
|
22475
|
-
sessionId:
|
|
23229
|
+
sessionId: environment.sessionId,
|
|
22476
23230
|
summary: {
|
|
22477
23231
|
declaredCount: declared.length,
|
|
22478
23232
|
liveReadyCount: liveReady.length,
|