@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/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()\` | Session state snapshot (advanced). |
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 payloadRaw = this.decodeBase64Url(parts[1]);
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(`defineRelationship failed: ${result.errors[0].message}`);
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(`getRelationships failed: ${result.errors[0].message}`);
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(`attach failed: ${result.errors[0].message}`);
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(`detach failed: ${result.errors[0].message}`);
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(`listRelated failed: ${result.errors[0].message}`);
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(`${label}: ${result.errors[0].message}`);
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
- return results[0];
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
- results[plan.offset + index] = items[index];
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 snapshot of the synced session heap.
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("No ontology configured. Run `granular init` first or pass `--ontology`.");
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((item) => item.name === requestedOntology);
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
- return environment.environment === requested || environment.envName === requested;
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((environment2) => matchesEnvironmentName(environment2, environmentName));
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 environment = await granular.openEnvironment({
22799
+ const connection = await granular.connect({
22059
22800
  ontology: ontologyId,
22060
- tag: environmentName,
22801
+ environment: environmentName,
22061
22802
  userId: options.userId ?? "granular-cli",
22062
22803
  permissions: options.permissions ?? ["default"]
22063
22804
  });
22064
- return await granular.environments.get(environment.environmentId);
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 session3 = await granular2["connectSession"]({ sessionId: options.sessionId });
22822
+ const environment2 = await granular2.connectSession({
22823
+ sessionId: options.sessionId
22824
+ });
22082
22825
  return {
22083
22826
  granular: granular2,
22084
- environment: session3.environment,
22085
- session: session3,
22086
- ontologyId: session3.ontologyId || session3.sandboxId
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("No ontology configured. Run `granular init` first or pass `--ontology`.");
22835
+ throw new Error(
22836
+ "No ontology configured. Run `granular init` first or pass `--ontology`."
22837
+ );
22093
22838
  }
22094
- const environment = await granular.openEnvironment({
22839
+ const environmentHandle = await granular.connect({
22095
22840
  ontology: ontologyId,
22096
- tag: options.environment ?? "dev",
22841
+ environment: options.environment ?? "dev",
22097
22842
  userId: options.userId ?? "granular-cli",
22098
22843
  permissions: options.permissions ?? ["default"]
22099
22844
  });
22100
- const session2 = await environment.sessions.create();
22845
+ const environment = await environmentHandle.createSession();
22101
22846
  return {
22102
22847
  granular,
22103
22848
  environment,
22104
- session: session2,
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.session.disconnect();
22859
+ await connection.environment.disconnect();
22115
22860
  } catch {
22116
- connection.session.disconnectTransport();
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: options.environment ?? "dev",
22895
+ environment: requestedEnvironment,
22150
22896
  userId: options.user,
22151
22897
  permissions: normalizePermissions(options.permissions)
22152
22898
  },
22153
- async ({ environment, session: session2, ontologyId }) => {
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.environment,
22160
- sessionId: session2.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
- "Environment": payload.environment,
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, session: session2, ontologyId }) => {
22952
+ async ({ environment, ontologyId }) => {
22207
22953
  const payload = {
22208
22954
  ontologyId,
22209
- sessionId: session2.sessionId,
22955
+ sessionId: environment.sessionId,
22210
22956
  environmentId: environment.environmentId,
22211
- heap: session2.getHeap()
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, session: session2, ontologyId }) => {
22980
+ async ({ environment, ontologyId }) => {
22235
22981
  const payload = {
22236
22982
  ontologyId,
22237
- sessionId: session2.sessionId,
22983
+ sessionId: environment.sessionId,
22238
22984
  environmentId: environment.environmentId,
22239
- document: documentToJson(session2.document)
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: options.environment ?? "dev",
23007
+ environment: requestedEnvironment,
22259
23008
  environmentId: options.environmentId,
22260
23009
  userId: options.user,
22261
23010
  permissions,
22262
23011
  createIfMissing: true
22263
23012
  });
22264
- const session2 = await granular.createSession({
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: session2.environmentId,
22272
- environment: session2.environment.environment,
22273
- sessionId: session2.sessionId,
22274
- subjectId: session2.subjectId,
22275
- versionId: session2.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
- "Environment": payload.environment,
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 session2.disconnect();
23043
+ await environment.disconnect();
22295
23044
  } catch {
22296
- session2.disconnectTransport();
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: options.environment ?? "dev",
23059
+ environment: requestedEnvironment,
22310
23060
  environmentId: options.environmentId,
22311
23061
  createIfMissing: false
22312
23062
  });
22313
- const items = await listSessionsForEnvironment(granular, environmentData.environmentId, status);
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.environment ?? environmentData.envName,
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, session: session2, ontologyId }) => {
22422
- const effects2 = sortEffects(session2.getEffects());
23175
+ async ({ environment, ontologyId }) => {
23176
+ const effects2 = sortEffects(environment.getEffects());
22423
23177
  const payload = {
22424
23178
  ontologyId,
22425
23179
  environmentId: environment.environmentId,
22426
- sessionId: session2.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, session: session2, ontologyId }) => {
22467
- const effects2 = sortEffects(session2.getEffects());
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: session2.sessionId,
23229
+ sessionId: environment.sessionId,
22476
23230
  summary: {
22477
23231
  declaredCount: declared.length,
22478
23232
  liveReadyCount: liveReady.length,