@xpert-ai/chatkit-types 0.6.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2,6 +2,9 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const constants = require("./constants.cjs");
4
4
  require("@langchain/core/messages/tool");
5
+ function isApprovalHostReference(value) {
6
+ return !!value && typeof value === "object" && "kind" in value && typeof value.kind === "string" && value.kind.length > 0 && "id" in value && typeof value.id === "string" && value.id.length > 0 && "expiresAt" in value && typeof value.expiresAt === "number" && Number.isFinite(value.expiresAt);
7
+ }
5
8
  function isLocalizedText(value) {
6
9
  return typeof value === "string" || !!value && typeof value === "object" && !Array.isArray(value) && Object.values(value).every((item) => typeof item === "string" || item === void 0);
7
10
  }
@@ -131,9 +134,7 @@ function normalizeHITLRequest(value) {
131
134
  const normalizedActionRequests = actionRequests.map(
132
135
  normalizeHITLActionRequest
133
136
  );
134
- const normalizedReviewConfigs = reviewConfigs.map(
135
- normalizeHITLReviewConfig
136
- );
137
+ const normalizedReviewConfigs = reviewConfigs.map(normalizeHITLReviewConfig);
137
138
  if (normalizedActionRequests.some((request) => request === null) || normalizedReviewConfigs.some((config2) => config2 === null)) {
138
139
  return null;
139
140
  }
@@ -141,6 +142,12 @@ function normalizeHITLRequest(value) {
141
142
  actionRequests: normalizedActionRequests,
142
143
  reviewConfigs: normalizedReviewConfigs
143
144
  };
145
+ if (value.host !== void 0) {
146
+ if (!isApprovalHostReference(value.host)) return null;
147
+ normalizedRequest.host = value.host;
148
+ }
149
+ if (typeof value.toolCallId === "string")
150
+ normalizedRequest.toolCallId = value.toolCallId;
144
151
  const elicitation = normalizeHITLMCPElicitation(value.elicitation);
145
152
  if (!elicitation || normalizedRequest.actionRequests.length !== 1) {
146
153
  return normalizedRequest;
@@ -605,6 +612,222 @@ function getMessageSkillUsages(message) {
605
612
  }
606
613
  const TOOL_OUTPUT_PRESENTATION_TYPE = "xpert.tool-output";
607
614
  const TOOL_OUTPUT_PRESENTATION_VERSION = 1;
615
+ function parseFileActivityContent(value) {
616
+ if (!value || typeof value !== "object") return null;
617
+ const part = value;
618
+ if (part.type !== "file_activity" || typeof part.id !== "string" || !part.id || !part.data || typeof part.data !== "object") return null;
619
+ const data = part.data;
620
+ if (data.version !== 1 || data.receiptId !== part.id || typeof data.toolCallId !== "string" || !data.toolCallId || typeof data.updatedAt !== "string" || !Number.isFinite(Date.parse(data.updatedAt))) return null;
621
+ const base = { version: 1, receiptId: part.id, toolCallId: data.toolCallId, updatedAt: data.updatedAt };
622
+ let receipt;
623
+ if (data.kind === "changes" && ["bounded", "partial", "unavailable"].includes(data.coverage) && Array.isArray(data.fileChanges)) {
624
+ const fileChanges = normalizeFileChanges(data.fileChanges);
625
+ if (fileChanges.length !== data.fileChanges.length) return null;
626
+ receipt = { ...base, kind: "changes", coverage: data.coverage, fileChanges };
627
+ } else if (data.kind === "delivery" && data.status === "success" && Array.isArray(data.outputs)) {
628
+ const outputs = normalizeFileOutputs(data.outputs);
629
+ if (outputs.length !== data.outputs.length) return null;
630
+ receipt = { ...base, kind: "delivery", status: "success", outputs };
631
+ } else if (data.kind === "delivery" && data.status === "error" && typeof data.error === "string") {
632
+ receipt = { ...base, kind: "delivery", status: "error", error: data.error };
633
+ } else return null;
634
+ return {
635
+ id: part.id,
636
+ type: "file_activity",
637
+ data: receipt,
638
+ ...typeof part.messageId === "string" ? { messageId: part.messageId } : {},
639
+ ...typeof part.executionId === "string" ? { executionId: part.executionId } : {},
640
+ ...typeof part.agentKey === "string" ? { agentKey: part.agentKey } : {},
641
+ ...typeof part.parentExecutionId === "string" ? { parentExecutionId: part.parentExecutionId } : {},
642
+ ...typeof part.runId === "string" ? { runId: part.runId } : {}
643
+ };
644
+ }
645
+ function getLegacyFileActivityContribution(value) {
646
+ var _a;
647
+ if (!value || typeof value !== "object") return null;
648
+ const part = value;
649
+ const step = part.type === "component" ? part.data : value;
650
+ if (!step || typeof step !== "object") return null;
651
+ const summary = step.taskSummary ?? ((_a = step._meta) == null ? void 0 : _a["xpertai/taskSummary"]);
652
+ const id = part.id ?? step.id;
653
+ return (summary == null ? void 0 : summary.version) === 1 && summary.fileActivityVersion === 1 && typeof summary.fileActivityToolCallId === "string" && Boolean(summary.fileActivityToolCallId) && typeof id === "string" && id !== summary.fileActivityToolCallId ? summary : null;
654
+ }
655
+ function isFileActivityContent(value) {
656
+ return Boolean(value && typeof value === "object" && "type" in value && value.type === "file_activity") || getLegacyFileActivityContribution(value) !== null;
657
+ }
658
+ function getFileActivityContribution(value) {
659
+ const part = parseFileActivityContent(value);
660
+ if (!part) return getLegacyFileActivityContribution(value);
661
+ const receipt = part.data;
662
+ return {
663
+ version: 1,
664
+ fileActivityVersion: 1,
665
+ fileActivityToolCallId: receipt.toolCallId,
666
+ ...receipt.kind === "changes" ? { fileChanges: receipt.fileChanges, fileChangeCoverage: receipt.coverage } : receipt.status === "success" ? { outputs: receipt.outputs } : {}
667
+ };
668
+ }
669
+ function upsertFileActivityContent(content, receipt) {
670
+ const index = content.findIndex((item) => {
671
+ var _a;
672
+ return ((_a = parseFileActivityContent(item)) == null ? void 0 : _a.id) === receipt.id;
673
+ });
674
+ if (index < 0) return [...content, receipt];
675
+ const previous = parseFileActivityContent(content[index]);
676
+ if (previous && Date.parse(previous.data.updatedAt) >= Date.parse(receipt.data.updatedAt)) return content;
677
+ return content.map((item, position) => position === index ? receipt : item);
678
+ }
679
+ function fileChangeRangeKey(resource) {
680
+ return JSON.stringify([resource.first.artifactId, resource.first.artifactVersionId, resource.last.artifactId, resource.last.artifactVersionId]);
681
+ }
682
+ const writeTools = /* @__PURE__ */ new Set(["sandbox_write_file", "sandbox_append_file", "sandbox_edit_file", "sandbox_multi_edit_file"]);
683
+ function normalizeFileChanges(value) {
684
+ if (!Array.isArray(value)) return [];
685
+ return value.filter((item) => {
686
+ if (!item || typeof item !== "object") return false;
687
+ const change = item;
688
+ return typeof change.id === "string" && typeof change.workspacePath === "string" && typeof change.title === "string" && ["added", "modified", "deleted", "unknown"].includes(change.operation ?? "") && ["observed", "legacy"].includes(change.coverage ?? "") && (!change.resource || change.resource.type === "file_change" && validVersion(change.resource.first) && validVersion(change.resource.last)) && validRevision(change.before) && validRevision(change.after);
689
+ }).map(({ id, title, workspacePath, operation, before, after, resource, coverage, messageId, startedAt, updatedAt }) => ({
690
+ id,
691
+ title,
692
+ workspacePath,
693
+ operation,
694
+ before: compactRevision(before),
695
+ after: compactRevision(after),
696
+ resource,
697
+ coverage,
698
+ messageId,
699
+ startedAt,
700
+ updatedAt
701
+ }));
702
+ }
703
+ function compactRevision(value) {
704
+ return value ? { sha256: value.sha256, size: value.size } : value;
705
+ }
706
+ function normalizeFileOutputs(value) {
707
+ if (!Array.isArray(value)) return [];
708
+ return value.flatMap((item) => {
709
+ if (!item || typeof item !== "object") return [];
710
+ const output = compactOutput(item);
711
+ return output ? [output] : [];
712
+ });
713
+ }
714
+ function compactOutput(value) {
715
+ if (!value || typeof value.id !== "string" || typeof value.title !== "string" || !["file", "image", "document", "spreadsheet", "presentation", "site", "url", "mcp_app"].includes(value.kind) || value.status !== void 0 && value.status !== "success") return null;
716
+ const ref = value.resource;
717
+ const resource = (ref == null ? void 0 : ref.type) === "artifact" && typeof ref.artifactId === "string" ? { type: "artifact", artifactId: ref.artifactId, ...typeof ref.artifactVersionId === "string" ? { artifactVersionId: ref.artifactVersionId } : {} } : (ref == null ? void 0 : ref.type) === "workspace_file" && typeof ref.workspacePath === "string" ? { type: "workspace_file", workspacePath: ref.workspacePath, fileAssetId: ref.fileAssetId, storageFileId: ref.storageFileId } : (ref == null ? void 0 : ref.type) === "url" && typeof ref.url === "string" ? { type: "url", url: ref.url } : void 0;
718
+ if (!resource) return null;
719
+ const { id, kind, title, description, status, origin, workspacePath, mimeType, size, sha256, messageId, updatedAt } = value;
720
+ return { id, kind, title, description, status, resource, origin, workspacePath, mimeType, size, sha256, messageId, updatedAt };
721
+ }
722
+ function validVersion(value) {
723
+ return Boolean(value && typeof value.artifactId === "string" && typeof value.artifactVersionId === "string");
724
+ }
725
+ function validRevision(value) {
726
+ return value == null || typeof value.sha256 === "string" && /^[a-f0-9]{64}$/.test(value.sha256) && Number.isSafeInteger(value.size) && value.size >= 0;
727
+ }
728
+ function mergeFileChanges(items) {
729
+ const byPath = /* @__PURE__ */ new Map();
730
+ for (const item of [...items].sort((a, b) => (a.startedAt ?? a.updatedAt ?? "").localeCompare(b.startedAt ?? b.updatedAt ?? ""))) {
731
+ const previous = byPath.get(item.workspacePath);
732
+ if (!previous || previous.coverage === "legacy") {
733
+ byPath.set(item.workspacePath, item);
734
+ continue;
735
+ }
736
+ if (item.coverage === "legacy") continue;
737
+ const latest = (item.updatedAt ?? "") >= (previous.updatedAt ?? "") ? item : previous;
738
+ const earliest = (item.startedAt ?? item.updatedAt ?? "") < (previous.startedAt ?? previous.updatedAt ?? "") ? item : previous;
739
+ const before = earliest.before;
740
+ const after = latest.after;
741
+ byPath.set(item.workspacePath, {
742
+ ...latest,
743
+ before,
744
+ after,
745
+ startedAt: earliest.startedAt ?? earliest.updatedAt,
746
+ operation: before === null ? "added" : after === null ? "deleted" : "modified",
747
+ resource: earliest.resource && latest.resource ? { type: "file_change", first: earliest.resource.first, last: latest.resource.last } : latest.resource
748
+ });
749
+ }
750
+ return [...byPath.values()].filter((item) => {
751
+ var _a, _b;
752
+ return item.coverage === "legacy" || ((_a = item.before) == null ? void 0 : _a.sha256) !== ((_b = item.after) == null ? void 0 : _b.sha256);
753
+ }).sort((a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? ""));
754
+ }
755
+ function projectMessageFileActivity(message, contribution) {
756
+ var _a, _b, _c, _d, _e;
757
+ const parts = Array.isArray(message.content) ? message.content : [];
758
+ const observed = [];
759
+ const legacyChanges = [];
760
+ const legacyOutputIds = /* @__PURE__ */ new Set();
761
+ const date = message.updatedAt ?? message.createdAt;
762
+ const updatedAt = date instanceof Date ? date.toISOString() : date;
763
+ const observedToolCalls = new Set(parts.flatMap((part) => {
764
+ var _a2, _b2, _c2;
765
+ const summary = getFileActivityContribution(part) ?? ((_a2 = part.data) == null ? void 0 : _a2.taskSummary) ?? ((_c2 = (_b2 = part.data) == null ? void 0 : _b2._meta) == null ? void 0 : _c2["xpertai/taskSummary"]);
766
+ return (summary == null ? void 0 : summary.fileActivityToolCallId) ? [summary.fileActivityToolCallId] : [];
767
+ }));
768
+ for (const part of parts) {
769
+ const receipt = getFileActivityContribution(part);
770
+ if (receipt) {
771
+ observed.push(receipt);
772
+ continue;
773
+ }
774
+ if ((part == null ? void 0 : part.type) !== "component" || !part.data) continue;
775
+ const data = part.data;
776
+ const explicit = data.taskSummary ?? ((_a = data._meta) == null ? void 0 : _a["xpertai/taskSummary"]);
777
+ if ((explicit == null ? void 0 : explicit.version) === 1) observed.push(explicit);
778
+ if (!writeTools.has(data.tool ?? "") || data.status !== "success") continue;
779
+ const path = (_b = data.input) == null ? void 0 : _b.file_path;
780
+ if (typeof path !== "string" || !path || path.startsWith("/") || path.split("/").includes("..")) continue;
781
+ legacyOutputIds.add(`workspace-file:${path}`);
782
+ if ((explicit == null ? void 0 : explicit.fileActivityVersion) === 1 || part.id && observedToolCalls.has(part.id)) continue;
783
+ legacyChanges.push({ id: `file-change:${path}`, title: path, workspacePath: path, operation: "unknown", coverage: "legacy", messageId: message.id, updatedAt });
784
+ }
785
+ if (!observed.length && !legacyOutputIds.size && !((_c = contribution.outputs) == null ? void 0 : _c.length) && !((_d = contribution.fileChanges) == null ? void 0 : _d.length)) return contribution;
786
+ const outputs = [...contribution.outputs ?? [], ...observed.flatMap((item) => item.outputs ?? [])];
787
+ const byId = /* @__PURE__ */ new Map();
788
+ for (const raw of outputs) {
789
+ const output = compactOutput(raw);
790
+ if (!output) continue;
791
+ if (legacyOutputIds.has(output.id) && output.origin !== "tool" && output.origin !== "integration") continue;
792
+ if ((((_e = byId.get(output.id)) == null ? void 0 : _e.updatedAt) ?? "") > (output.updatedAt ?? updatedAt ?? "")) continue;
793
+ byId.set(output.id, { ...output, origin: output.origin ?? "legacy", messageId: message.id ?? output.messageId, updatedAt: output.updatedAt ?? updatedAt });
794
+ }
795
+ const changes = mergeFileChanges([
796
+ ...legacyChanges,
797
+ ...normalizeFileChanges(contribution.fileChanges),
798
+ ...observed.flatMap((item) => normalizeFileChanges(item.fileChanges))
799
+ ].map((item) => ({ ...item, messageId: message.id ?? item.messageId })));
800
+ const coverage = [contribution.fileChangeCoverage, ...observed.map((item) => item.fileChangeCoverage)];
801
+ const fileChangeCoverage = coverage.includes("unavailable") ? "unavailable" : coverage.includes("partial") ? "partial" : coverage.includes("bounded") ? "bounded" : void 0;
802
+ return { ...contribution, fileActivityVersion: 1, fileChangeCoverage, outputs: [...byId.values()], fileChanges: changes };
803
+ }
804
+ function parseFileChangeReport(value) {
805
+ if (!value || typeof value !== "object") return null;
806
+ const report = value;
807
+ const revision = (item) => item === null || Boolean(item && validRevision(item) && (item.text === void 0 || typeof item.text === "string" && item.text.length <= 32768));
808
+ return report.schema === "xpert.file-change.v1" && typeof report.workspacePath === "string" && revision(report.before) && revision(report.after) ? report : null;
809
+ }
810
+ const MAX_DIFF_CELLS = 4e6;
811
+ function countFileChangeLines(report) {
812
+ var _a, _b;
813
+ if (report.before && report.before.text === void 0 || report.after && report.after.text === void 0) return { status: "unavailable" };
814
+ const lines = (text) => text ? text.replace(/\r\n/g, "\n").replace(/\n$/, "").split("\n") : [];
815
+ const before = lines(((_a = report.before) == null ? void 0 : _a.text) ?? ""), after = lines(((_b = report.after) == null ? void 0 : _b.text) ?? "");
816
+ let start = 0, endBefore = before.length, endAfter = after.length;
817
+ while (start < endBefore && start < endAfter && before[start] === after[start]) start++;
818
+ while (endBefore > start && endAfter > start && before[endBefore - 1] === after[endAfter - 1]) {
819
+ endBefore--;
820
+ endAfter--;
821
+ }
822
+ const n = endBefore - start, m = endAfter - start;
823
+ if (n * m > MAX_DIFF_CELLS) return { status: "unavailable" };
824
+ let previous = new Uint32Array(m + 1), current = new Uint32Array(m + 1);
825
+ for (let i = 0; i < n; i++) {
826
+ for (let j = 0; j < m; j++) current[j + 1] = before[start + i] === after[start + j] ? previous[j] + 1 : Math.max(previous[j + 1], current[j]);
827
+ [previous, current] = [current, previous];
828
+ }
829
+ return { status: "ready", added: m - previous[m], removed: n - previous[m] };
830
+ }
608
831
  exports.CHAT_EVENT_TYPE_FOLLOW_UP_CONSUMED = constants.CHAT_EVENT_TYPE_FOLLOW_UP_CONSUMED;
609
832
  exports.ChatMessageEventTypeEnum = constants.ChatMessageEventTypeEnum;
610
833
  exports.ChatMessageStepCategory = constants.ChatMessageStepCategory;
@@ -625,12 +848,18 @@ exports.TOOL_OUTPUT_PRESENTATION_TYPE = TOOL_OUTPUT_PRESENTATION_TYPE;
625
848
  exports.TOOL_OUTPUT_PRESENTATION_VERSION = TOOL_OUTPUT_PRESENTATION_VERSION;
626
849
  exports.chatSkillUsageKey = chatSkillUsageKey;
627
850
  exports.clampPetPosition = clampPetPosition;
851
+ exports.countFileChangeLines = countFileChangeLines;
852
+ exports.fileChangeRangeKey = fileChangeRangeKey;
853
+ exports.getFileActivityContribution = getFileActivityContribution;
854
+ exports.getLegacyFileActivityContribution = getLegacyFileActivityContribution;
628
855
  exports.getMessageSkillUsages = getMessageSkillUsages;
629
856
  exports.getPinnedPetPosition = getPinnedPetPosition;
857
+ exports.isApprovalHostReference = isApprovalHostReference;
630
858
  exports.isClientToolInterrupt = isClientToolInterrupt;
631
859
  exports.isClientToolInterruptPayload = isClientToolInterruptPayload;
632
860
  exports.isClientToolInterruptTask = isClientToolInterruptTask;
633
861
  exports.isClientToolRequest = isClientToolRequest;
862
+ exports.isFileActivityContent = isFileActivityContent;
634
863
  exports.isHITLDecisionType = isHITLDecisionType;
635
864
  exports.isHITLInterrupt = isHITLInterrupt;
636
865
  exports.isHITLInterruptPayload = isHITLInterruptPayload;
@@ -646,14 +875,21 @@ exports.isToolCallInterruptPayload = isToolCallInterruptPayload;
646
875
  exports.isToolCallInterruptTask = isToolCallInterruptTask;
647
876
  exports.isToolCallRequest = isToolCallRequest;
648
877
  exports.mergeChatSkillUsages = mergeChatSkillUsages;
878
+ exports.mergeFileChanges = mergeFileChanges;
649
879
  exports.mergePetSpriteAtlas = mergePetSpriteAtlas;
650
880
  exports.normalizeBoundsPadding = normalizeBoundsPadding;
651
881
  exports.normalizeChatSkillUsages = normalizeChatSkillUsages;
882
+ exports.normalizeFileChanges = normalizeFileChanges;
883
+ exports.normalizeFileOutputs = normalizeFileOutputs;
652
884
  exports.normalizeHITLRequest = normalizeHITLRequest;
653
885
  exports.normalizePetOptions = normalizePetOptions;
654
886
  exports.normalizeRequestLanguage = normalizeRequestLanguage;
655
887
  exports.normalizeThreadReference = normalizeThreadReference;
888
+ exports.parseFileActivityContent = parseFileActivityContent;
889
+ exports.parseFileChangeReport = parseFileChangeReport;
656
890
  exports.petSpriteAtlas = petSpriteAtlas;
891
+ exports.projectMessageFileActivity = projectMessageFileActivity;
657
892
  exports.resolveLocalizedText = resolveLocalizedText;
658
893
  exports.resolvePetCharacter = resolvePetCharacter;
894
+ exports.upsertFileActivityContent = upsertFileActivityContent;
659
895
  //# sourceMappingURL=index.cjs.map