@xpert-ai/chatkit-types 0.6.2 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -187,6 +187,22 @@ export declare interface ChatEventEnvelope<T = unknown> {
187
187
  data: T;
188
188
  }
189
189
 
190
+ export declare type ChatFileChange = {
191
+ id: string;
192
+ workspacePath: string;
193
+ title: string;
194
+ operation: 'added' | 'modified' | 'deleted' | 'unknown';
195
+ before?: FileRevision | null;
196
+ after?: FileRevision | null;
197
+ resource?: Extract<ChatTaskSummaryResourceReference, {
198
+ type: 'file_change';
199
+ }>;
200
+ coverage: 'observed' | 'legacy';
201
+ messageId?: string;
202
+ startedAt?: string;
203
+ updatedAt?: string;
204
+ };
205
+
190
206
  export declare const CHATKIT_TASK_SUMMARY_OPEN_RESOURCE_EFFECT: "task_summary.open_resource";
191
207
 
192
208
  export declare type ChatKitClientSecretObject = {
@@ -1172,6 +1188,12 @@ export declare type ChatTaskSummaryOutput = {
1172
1188
  resource?: ChatTaskSummaryResourceReference;
1173
1189
  messageId?: string;
1174
1190
  updatedAt?: string;
1191
+ /** Only host-verified, explicitly presented files get message-end cards. */
1192
+ origin?: 'tool' | 'integration' | 'legacy';
1193
+ workspacePath?: string;
1194
+ mimeType?: string;
1195
+ size?: number;
1196
+ sha256?: string;
1175
1197
  };
1176
1198
 
1177
1199
  export declare type ChatTaskSummaryOutputKind = 'file' | 'image' | 'document' | 'spreadsheet' | 'presentation' | 'site' | 'url' | 'mcp_app';
@@ -1196,7 +1218,8 @@ export declare type ChatTaskSummaryResourceReference = {
1196
1218
  } | {
1197
1219
  type: 'artifact';
1198
1220
  artifactId: string;
1199
- } | {
1221
+ artifactVersionId?: string;
1222
+ } | FileChangeResource | FileChangeSetResource | {
1200
1223
  type: 'browser';
1201
1224
  serviceId?: string;
1202
1225
  url?: string;
@@ -1287,6 +1310,9 @@ declare type ControlSize = '3xs' | '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2
1287
1310
 
1288
1311
  declare type ControlVariant = 'solid' | 'soft' | 'outline' | 'ghost';
1289
1312
 
1313
+ /** Exact line LCS with bounded CPU/memory. Unknown text never becomes zero changes. */
1314
+ export declare function countFileChangeLines(report: FileChangeReport): FileChangeLineStats;
1315
+
1290
1316
  declare type CustomApiConfig = {
1291
1317
  /**
1292
1318
  * The URL (relative or absolute) of the ChatKit API. The configured endpoint
@@ -1394,6 +1420,85 @@ export declare type Entity = {
1394
1420
 
1395
1421
  export declare type EventHandler<K extends keyof ChatKitEvents> = (event: ChatKitEvents[K]) => any;
1396
1422
 
1423
+ export declare type FileActivityMessage = {
1424
+ id?: string;
1425
+ content?: unknown;
1426
+ taskSummary?: TChatTaskSummaryContribution;
1427
+ updatedAt?: string | Date;
1428
+ createdAt?: string | Date;
1429
+ };
1430
+
1431
+ /** Host-owned facts from a tool execution, never an additional tool invocation. */
1432
+ export declare type FileActivityReceipt = {
1433
+ version: 1;
1434
+ receiptId: string;
1435
+ toolCallId: string;
1436
+ updatedAt: string;
1437
+ } & ({
1438
+ kind: 'changes';
1439
+ coverage: 'bounded' | 'partial' | 'unavailable';
1440
+ fileChanges: ChatFileChange[];
1441
+ } | {
1442
+ kind: 'delivery';
1443
+ status: 'success';
1444
+ outputs: ChatTaskSummaryOutput[];
1445
+ } | {
1446
+ kind: 'delivery';
1447
+ status: 'error';
1448
+ error: string;
1449
+ });
1450
+
1451
+ export declare type FileChangeLineStats = {
1452
+ status: 'ready';
1453
+ added: number;
1454
+ removed: number;
1455
+ } | {
1456
+ status: 'unavailable';
1457
+ };
1458
+
1459
+ /** Stable cache identity for a fixed review range; never identifies mutable workspace bytes. */
1460
+ export declare function fileChangeRangeKey(resource: Extract<ChatTaskSummaryResourceReference, {
1461
+ type: 'file_change';
1462
+ }>): string;
1463
+
1464
+ /** Private review payload. Never include text/diffs in compact task summaries. */
1465
+ export declare type FileChangeReport = {
1466
+ schema: 'xpert.file-change.v1';
1467
+ workspacePath: string;
1468
+ before: (FileRevision & {
1469
+ text?: string;
1470
+ }) | null;
1471
+ after: (FileRevision & {
1472
+ text?: string;
1473
+ }) | null;
1474
+ };
1475
+
1476
+ export declare type FileChangeResource = {
1477
+ type: 'file_change';
1478
+ first: {
1479
+ artifactId: string;
1480
+ artifactVersionId: string;
1481
+ };
1482
+ last: {
1483
+ artifactId: string;
1484
+ artifactVersionId: string;
1485
+ };
1486
+ };
1487
+
1488
+ export declare type FileChangeSetResource = {
1489
+ type: 'file_change_set';
1490
+ messageId: string;
1491
+ changes: {
1492
+ workspacePath: string;
1493
+ resource?: FileChangeResource;
1494
+ }[];
1495
+ };
1496
+
1497
+ export declare type FileRevision = {
1498
+ sha256: string;
1499
+ size: number;
1500
+ };
1501
+
1397
1502
  export declare type FileUploadStrategy = {
1398
1503
  type: 'two_phase';
1399
1504
  } | {
@@ -1420,6 +1525,11 @@ export declare type Form = {
1420
1525
  direction?: 'row' | 'col';
1421
1526
  } & BoxBaseProps;
1422
1527
 
1528
+ export declare function getFileActivityContribution(value: unknown): TChatTaskSummaryContribution | null;
1529
+
1530
+ /** Compatibility uses explicit metadata and the original call identity, never labels or ID suffixes. */
1531
+ export declare function getLegacyFileActivityContribution(value: unknown): TChatTaskSummaryContribution | null;
1532
+
1423
1533
  /** Works for both streamed tool components and persisted message summaries. */
1424
1534
  export declare function getMessageSkillUsages(message: {
1425
1535
  content?: unknown;
@@ -1670,6 +1780,8 @@ export declare function isClientToolInterruptTask(value: unknown): value is Clie
1670
1780
 
1671
1781
  export declare function isClientToolRequest(value: unknown): value is ClientToolRequest;
1672
1782
 
1783
+ export declare function isFileActivityContent(value: unknown): boolean;
1784
+
1673
1785
  export declare function isHITLDecisionType(value: unknown): value is HITLDecisionType;
1674
1786
 
1675
1787
  export declare function isHITLInterrupt(value: unknown): value is HITLInterrupt;
@@ -1764,6 +1876,9 @@ export declare type Markdown = {
1764
1876
  /** Merge only observations belonging to the same message. Keep the first read. */
1765
1877
  export declare function mergeChatSkillUsages(...groups: ReadonlyArray<readonly ChatSkillUsage[] | undefined>): ChatSkillUsage[];
1766
1878
 
1879
+ /** Collapse observed operations to the net change, retaining immutable first/last review references. */
1880
+ export declare function mergeFileChanges(items: ChatFileChange[]): ChatFileChange[];
1881
+
1767
1882
  export declare function mergePetSpriteAtlas(override?: ChatKitPetSpriteAtlas): PetSpriteAtlasDefinition;
1768
1883
 
1769
1884
  export declare type MessageContentImageUrl = {
@@ -1779,6 +1894,17 @@ export declare type MessageContentText = {
1779
1894
  text: string;
1780
1895
  };
1781
1896
 
1897
+ export declare type MessageFileChangeStats = {
1898
+ messageId: string;
1899
+ items: {
1900
+ workspacePath: string;
1901
+ resource?: Extract<ChatTaskSummaryResourceReference, {
1902
+ type: 'file_change';
1903
+ }>;
1904
+ stats: FileChangeLineStats;
1905
+ }[];
1906
+ };
1907
+
1782
1908
  export declare type ModelOption = {
1783
1909
  /** Identifier used when submitting a message. */
1784
1910
  id: string;
@@ -1812,6 +1938,10 @@ export declare type NormalizedPetOptions = {
1812
1938
  imageRendering: NonNullable<ChatKitPetOptions['imageRendering']>;
1813
1939
  };
1814
1940
 
1941
+ export declare function normalizeFileChanges(value: unknown): ChatFileChange[];
1942
+
1943
+ export declare function normalizeFileOutputs(value: unknown): ChatTaskSummaryOutput[];
1944
+
1815
1945
  export declare function normalizeHITLRequest(value: unknown): HITLRequest | null;
1816
1946
 
1817
1947
  export declare function normalizePetOptions(pet: ChatKitOptions['pet'] | null): NormalizedPetOptions | null;
@@ -1820,6 +1950,10 @@ export declare function normalizeRequestLanguage(locale?: string | null): string
1820
1950
 
1821
1951
  export declare function normalizeThreadReference(value: unknown): ChatKitThreadReference | null;
1822
1952
 
1953
+ export declare function parseFileActivityContent(value: unknown): TMessageContentFileActivity | null;
1954
+
1955
+ export declare function parseFileChangeReport(value: unknown): FileChangeReport | null;
1956
+
1823
1957
  export declare const PET_ANIMATION_NAMES: readonly ["idle", "running-right", "running-left", "waving", "jumping", "failed", "waiting", "running", "review"];
1824
1958
 
1825
1959
  export declare type PetFrameAnimationDefinition = {
@@ -1905,6 +2039,9 @@ export declare type PetViewport = {
1905
2039
  height: number;
1906
2040
  };
1907
2041
 
2042
+ /** Shared live/history projection. Proven tool writes move out of outputs, never filename-based classification. */
2043
+ export declare function projectMessageFileActivity(message: FileActivityMessage, contribution: TChatTaskSummaryContribution): TChatTaskSummaryContribution;
2044
+
1908
2045
  export declare type RadioGroup = {
1909
2046
  type: 'RadioGroup';
1910
2047
  key?: string;
@@ -2202,6 +2339,11 @@ export declare type TChatTaskSummaryContribution = {
2202
2339
  outputs?: ChatTaskSummaryOutput[];
2203
2340
  sources?: ChatTaskSummarySource[];
2204
2341
  skillUsages?: ChatSkillUsage[];
2342
+ /** Presence marks the new semantic projection; old writes are never deliveries. */
2343
+ fileActivityVersion?: 1;
2344
+ fileActivityToolCallId?: string;
2345
+ fileChangeCoverage?: 'bounded' | 'partial' | 'unavailable';
2346
+ fileChanges?: ChatFileChange[];
2205
2347
  };
2206
2348
 
2207
2349
  /**
@@ -2505,7 +2647,7 @@ export declare type TMessageContent = string | TMessageContentComplex[];
2505
2647
  /**
2506
2648
  * Enhance {@link MessageContentComplex} in Langchain.js
2507
2649
  */
2508
- export declare type TMessageContentComplex = (TMessageContentText | TMessageContentReasoning | MessageContentImageUrl | TMessageContentComponent | TMessageContentMemory | (Record<string, any> & {
2650
+ export declare type TMessageContentComplex = (TMessageContentText | TMessageContentReasoning | MessageContentImageUrl | TMessageContentComponent | TMessageContentFileActivity | TMessageContentMemory | (Record<string, any> & {
2509
2651
  type?: 'text' | 'image_url' | string;
2510
2652
  }) | (Record<string, any> & {
2511
2653
  type?: never;
@@ -2533,6 +2675,17 @@ export declare type TMessageContentComponent<T extends object = object> = {
2533
2675
  runId?: string;
2534
2676
  };
2535
2677
 
2678
+ export declare type TMessageContentFileActivity = {
2679
+ id: string;
2680
+ type: 'file_activity';
2681
+ data: FileActivityReceipt;
2682
+ messageId?: string;
2683
+ executionId?: string;
2684
+ agentKey?: string;
2685
+ parentExecutionId?: string;
2686
+ runId?: string;
2687
+ };
2688
+
2536
2689
  /**
2537
2690
  * MCP App component item in a LangChain-compatible complex message content
2538
2691
  * array.
@@ -2756,6 +2909,9 @@ export declare type TXpertChatTarget = {
2756
2909
  executionId?: string;
2757
2910
  };
2758
2911
 
2912
+ /** Receipts are immutable terminal facts; replay replaces by identity, never appends a second operation. */
2913
+ export declare function upsertFileActivityContent<T>(content: T[], receipt: TMessageContentFileActivity): (T | TMessageContentFileActivity)[];
2914
+
2759
2915
  export declare type UserMessageContent = unknown;
2760
2916
 
2761
2917
  export declare type WidgetComponent = TextComponent | Title | Caption | Badge | Markdown | Box | Row | Col | Divider | Icon | Image_2 | Button | Checkbox | Spacer | Select | DatePicker | Form | Input | Label | RadioGroup | Textarea | Transition;
package/dist/index.js CHANGED
@@ -603,6 +603,222 @@ function getMessageSkillUsages(message) {
603
603
  }
604
604
  const TOOL_OUTPUT_PRESENTATION_TYPE = "xpert.tool-output";
605
605
  const TOOL_OUTPUT_PRESENTATION_VERSION = 1;
606
+ function parseFileActivityContent(value) {
607
+ if (!value || typeof value !== "object") return null;
608
+ const part = value;
609
+ if (part.type !== "file_activity" || typeof part.id !== "string" || !part.id || !part.data || typeof part.data !== "object") return null;
610
+ const data = part.data;
611
+ 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;
612
+ const base = { version: 1, receiptId: part.id, toolCallId: data.toolCallId, updatedAt: data.updatedAt };
613
+ let receipt;
614
+ if (data.kind === "changes" && ["bounded", "partial", "unavailable"].includes(data.coverage) && Array.isArray(data.fileChanges)) {
615
+ const fileChanges = normalizeFileChanges(data.fileChanges);
616
+ if (fileChanges.length !== data.fileChanges.length) return null;
617
+ receipt = { ...base, kind: "changes", coverage: data.coverage, fileChanges };
618
+ } else if (data.kind === "delivery" && data.status === "success" && Array.isArray(data.outputs)) {
619
+ const outputs = normalizeFileOutputs(data.outputs);
620
+ if (outputs.length !== data.outputs.length) return null;
621
+ receipt = { ...base, kind: "delivery", status: "success", outputs };
622
+ } else if (data.kind === "delivery" && data.status === "error" && typeof data.error === "string") {
623
+ receipt = { ...base, kind: "delivery", status: "error", error: data.error };
624
+ } else return null;
625
+ return {
626
+ id: part.id,
627
+ type: "file_activity",
628
+ data: receipt,
629
+ ...typeof part.messageId === "string" ? { messageId: part.messageId } : {},
630
+ ...typeof part.executionId === "string" ? { executionId: part.executionId } : {},
631
+ ...typeof part.agentKey === "string" ? { agentKey: part.agentKey } : {},
632
+ ...typeof part.parentExecutionId === "string" ? { parentExecutionId: part.parentExecutionId } : {},
633
+ ...typeof part.runId === "string" ? { runId: part.runId } : {}
634
+ };
635
+ }
636
+ function getLegacyFileActivityContribution(value) {
637
+ var _a;
638
+ if (!value || typeof value !== "object") return null;
639
+ const part = value;
640
+ const step = part.type === "component" ? part.data : value;
641
+ if (!step || typeof step !== "object") return null;
642
+ const summary = step.taskSummary ?? ((_a = step._meta) == null ? void 0 : _a["xpertai/taskSummary"]);
643
+ const id = part.id ?? step.id;
644
+ 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;
645
+ }
646
+ function isFileActivityContent(value) {
647
+ return Boolean(value && typeof value === "object" && "type" in value && value.type === "file_activity") || getLegacyFileActivityContribution(value) !== null;
648
+ }
649
+ function getFileActivityContribution(value) {
650
+ const part = parseFileActivityContent(value);
651
+ if (!part) return getLegacyFileActivityContribution(value);
652
+ const receipt = part.data;
653
+ return {
654
+ version: 1,
655
+ fileActivityVersion: 1,
656
+ fileActivityToolCallId: receipt.toolCallId,
657
+ ...receipt.kind === "changes" ? { fileChanges: receipt.fileChanges, fileChangeCoverage: receipt.coverage } : receipt.status === "success" ? { outputs: receipt.outputs } : {}
658
+ };
659
+ }
660
+ function upsertFileActivityContent(content, receipt) {
661
+ const index = content.findIndex((item) => {
662
+ var _a;
663
+ return ((_a = parseFileActivityContent(item)) == null ? void 0 : _a.id) === receipt.id;
664
+ });
665
+ if (index < 0) return [...content, receipt];
666
+ const previous = parseFileActivityContent(content[index]);
667
+ if (previous && Date.parse(previous.data.updatedAt) >= Date.parse(receipt.data.updatedAt)) return content;
668
+ return content.map((item, position) => position === index ? receipt : item);
669
+ }
670
+ function fileChangeRangeKey(resource) {
671
+ return JSON.stringify([resource.first.artifactId, resource.first.artifactVersionId, resource.last.artifactId, resource.last.artifactVersionId]);
672
+ }
673
+ const writeTools = /* @__PURE__ */ new Set(["sandbox_write_file", "sandbox_append_file", "sandbox_edit_file", "sandbox_multi_edit_file"]);
674
+ function normalizeFileChanges(value) {
675
+ if (!Array.isArray(value)) return [];
676
+ return value.filter((item) => {
677
+ if (!item || typeof item !== "object") return false;
678
+ const change = item;
679
+ 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);
680
+ }).map(({ id, title, workspacePath, operation, before, after, resource, coverage, messageId, startedAt, updatedAt }) => ({
681
+ id,
682
+ title,
683
+ workspacePath,
684
+ operation,
685
+ before: compactRevision(before),
686
+ after: compactRevision(after),
687
+ resource,
688
+ coverage,
689
+ messageId,
690
+ startedAt,
691
+ updatedAt
692
+ }));
693
+ }
694
+ function compactRevision(value) {
695
+ return value ? { sha256: value.sha256, size: value.size } : value;
696
+ }
697
+ function normalizeFileOutputs(value) {
698
+ if (!Array.isArray(value)) return [];
699
+ return value.flatMap((item) => {
700
+ if (!item || typeof item !== "object") return [];
701
+ const output = compactOutput(item);
702
+ return output ? [output] : [];
703
+ });
704
+ }
705
+ function compactOutput(value) {
706
+ 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;
707
+ const ref = value.resource;
708
+ 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;
709
+ if (!resource) return null;
710
+ const { id, kind, title, description, status, origin, workspacePath, mimeType, size, sha256, messageId, updatedAt } = value;
711
+ return { id, kind, title, description, status, resource, origin, workspacePath, mimeType, size, sha256, messageId, updatedAt };
712
+ }
713
+ function validVersion(value) {
714
+ return Boolean(value && typeof value.artifactId === "string" && typeof value.artifactVersionId === "string");
715
+ }
716
+ function validRevision(value) {
717
+ return value == null || typeof value.sha256 === "string" && /^[a-f0-9]{64}$/.test(value.sha256) && Number.isSafeInteger(value.size) && value.size >= 0;
718
+ }
719
+ function mergeFileChanges(items) {
720
+ const byPath = /* @__PURE__ */ new Map();
721
+ for (const item of [...items].sort((a, b) => (a.startedAt ?? a.updatedAt ?? "").localeCompare(b.startedAt ?? b.updatedAt ?? ""))) {
722
+ const previous = byPath.get(item.workspacePath);
723
+ if (!previous || previous.coverage === "legacy") {
724
+ byPath.set(item.workspacePath, item);
725
+ continue;
726
+ }
727
+ if (item.coverage === "legacy") continue;
728
+ const latest = (item.updatedAt ?? "") >= (previous.updatedAt ?? "") ? item : previous;
729
+ const earliest = (item.startedAt ?? item.updatedAt ?? "") < (previous.startedAt ?? previous.updatedAt ?? "") ? item : previous;
730
+ const before = earliest.before;
731
+ const after = latest.after;
732
+ byPath.set(item.workspacePath, {
733
+ ...latest,
734
+ before,
735
+ after,
736
+ startedAt: earliest.startedAt ?? earliest.updatedAt,
737
+ operation: before === null ? "added" : after === null ? "deleted" : "modified",
738
+ resource: earliest.resource && latest.resource ? { type: "file_change", first: earliest.resource.first, last: latest.resource.last } : latest.resource
739
+ });
740
+ }
741
+ return [...byPath.values()].filter((item) => {
742
+ var _a, _b;
743
+ return item.coverage === "legacy" || ((_a = item.before) == null ? void 0 : _a.sha256) !== ((_b = item.after) == null ? void 0 : _b.sha256);
744
+ }).sort((a, b) => (b.updatedAt ?? "").localeCompare(a.updatedAt ?? ""));
745
+ }
746
+ function projectMessageFileActivity(message, contribution) {
747
+ var _a, _b, _c, _d, _e;
748
+ const parts = Array.isArray(message.content) ? message.content : [];
749
+ const observed = [];
750
+ const legacyChanges = [];
751
+ const legacyOutputIds = /* @__PURE__ */ new Set();
752
+ const date = message.updatedAt ?? message.createdAt;
753
+ const updatedAt = date instanceof Date ? date.toISOString() : date;
754
+ const observedToolCalls = new Set(parts.flatMap((part) => {
755
+ var _a2, _b2, _c2;
756
+ 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"]);
757
+ return (summary == null ? void 0 : summary.fileActivityToolCallId) ? [summary.fileActivityToolCallId] : [];
758
+ }));
759
+ for (const part of parts) {
760
+ const receipt = getFileActivityContribution(part);
761
+ if (receipt) {
762
+ observed.push(receipt);
763
+ continue;
764
+ }
765
+ if ((part == null ? void 0 : part.type) !== "component" || !part.data) continue;
766
+ const data = part.data;
767
+ const explicit = data.taskSummary ?? ((_a = data._meta) == null ? void 0 : _a["xpertai/taskSummary"]);
768
+ if ((explicit == null ? void 0 : explicit.version) === 1) observed.push(explicit);
769
+ if (!writeTools.has(data.tool ?? "") || data.status !== "success") continue;
770
+ const path = (_b = data.input) == null ? void 0 : _b.file_path;
771
+ if (typeof path !== "string" || !path || path.startsWith("/") || path.split("/").includes("..")) continue;
772
+ legacyOutputIds.add(`workspace-file:${path}`);
773
+ if ((explicit == null ? void 0 : explicit.fileActivityVersion) === 1 || part.id && observedToolCalls.has(part.id)) continue;
774
+ legacyChanges.push({ id: `file-change:${path}`, title: path, workspacePath: path, operation: "unknown", coverage: "legacy", messageId: message.id, updatedAt });
775
+ }
776
+ if (!observed.length && !legacyOutputIds.size && !((_c = contribution.outputs) == null ? void 0 : _c.length) && !((_d = contribution.fileChanges) == null ? void 0 : _d.length)) return contribution;
777
+ const outputs = [...contribution.outputs ?? [], ...observed.flatMap((item) => item.outputs ?? [])];
778
+ const byId = /* @__PURE__ */ new Map();
779
+ for (const raw of outputs) {
780
+ const output = compactOutput(raw);
781
+ if (!output) continue;
782
+ if (legacyOutputIds.has(output.id) && output.origin !== "tool" && output.origin !== "integration") continue;
783
+ if ((((_e = byId.get(output.id)) == null ? void 0 : _e.updatedAt) ?? "") > (output.updatedAt ?? updatedAt ?? "")) continue;
784
+ byId.set(output.id, { ...output, origin: output.origin ?? "legacy", messageId: message.id ?? output.messageId, updatedAt: output.updatedAt ?? updatedAt });
785
+ }
786
+ const changes = mergeFileChanges([
787
+ ...legacyChanges,
788
+ ...normalizeFileChanges(contribution.fileChanges),
789
+ ...observed.flatMap((item) => normalizeFileChanges(item.fileChanges))
790
+ ].map((item) => ({ ...item, messageId: message.id ?? item.messageId })));
791
+ const coverage = [contribution.fileChangeCoverage, ...observed.map((item) => item.fileChangeCoverage)];
792
+ const fileChangeCoverage = coverage.includes("unavailable") ? "unavailable" : coverage.includes("partial") ? "partial" : coverage.includes("bounded") ? "bounded" : void 0;
793
+ return { ...contribution, fileActivityVersion: 1, fileChangeCoverage, outputs: [...byId.values()], fileChanges: changes };
794
+ }
795
+ function parseFileChangeReport(value) {
796
+ if (!value || typeof value !== "object") return null;
797
+ const report = value;
798
+ const revision = (item) => item === null || Boolean(item && validRevision(item) && (item.text === void 0 || typeof item.text === "string" && item.text.length <= 32768));
799
+ return report.schema === "xpert.file-change.v1" && typeof report.workspacePath === "string" && revision(report.before) && revision(report.after) ? report : null;
800
+ }
801
+ const MAX_DIFF_CELLS = 4e6;
802
+ function countFileChangeLines(report) {
803
+ var _a, _b;
804
+ if (report.before && report.before.text === void 0 || report.after && report.after.text === void 0) return { status: "unavailable" };
805
+ const lines = (text) => text ? text.replace(/\r\n/g, "\n").replace(/\n$/, "").split("\n") : [];
806
+ const before = lines(((_a = report.before) == null ? void 0 : _a.text) ?? ""), after = lines(((_b = report.after) == null ? void 0 : _b.text) ?? "");
807
+ let start = 0, endBefore = before.length, endAfter = after.length;
808
+ while (start < endBefore && start < endAfter && before[start] === after[start]) start++;
809
+ while (endBefore > start && endAfter > start && before[endBefore - 1] === after[endAfter - 1]) {
810
+ endBefore--;
811
+ endAfter--;
812
+ }
813
+ const n = endBefore - start, m = endAfter - start;
814
+ if (n * m > MAX_DIFF_CELLS) return { status: "unavailable" };
815
+ let previous = new Uint32Array(m + 1), current = new Uint32Array(m + 1);
816
+ for (let i = 0; i < n; i++) {
817
+ 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]);
818
+ [previous, current] = [current, previous];
819
+ }
820
+ return { status: "ready", added: m - previous[m], removed: n - previous[m] };
821
+ }
606
822
  export {
607
823
  CHATKIT_TASK_SUMMARY_OPEN_RESOURCE_EFFECT,
608
824
  CHAT_EVENT_TYPE_FOLLOW_UP_CONSUMED,
@@ -624,12 +840,17 @@ export {
624
840
  TOOL_OUTPUT_PRESENTATION_VERSION,
625
841
  chatSkillUsageKey,
626
842
  clampPetPosition,
843
+ countFileChangeLines,
844
+ fileChangeRangeKey,
845
+ getFileActivityContribution,
846
+ getLegacyFileActivityContribution,
627
847
  getMessageSkillUsages,
628
848
  getPinnedPetPosition,
629
849
  isClientToolInterrupt,
630
850
  isClientToolInterruptPayload,
631
851
  isClientToolInterruptTask,
632
852
  isClientToolRequest,
853
+ isFileActivityContent,
633
854
  isHITLDecisionType,
634
855
  isHITLInterrupt,
635
856
  isHITLInterruptPayload,
@@ -645,15 +866,22 @@ export {
645
866
  isToolCallInterruptTask,
646
867
  isToolCallRequest,
647
868
  mergeChatSkillUsages,
869
+ mergeFileChanges,
648
870
  mergePetSpriteAtlas,
649
871
  normalizeBoundsPadding,
650
872
  normalizeChatSkillUsages,
873
+ normalizeFileChanges,
874
+ normalizeFileOutputs,
651
875
  normalizeHITLRequest,
652
876
  normalizePetOptions,
653
877
  normalizeRequestLanguage,
654
878
  normalizeThreadReference,
879
+ parseFileActivityContent,
880
+ parseFileChangeReport,
655
881
  petSpriteAtlas,
882
+ projectMessageFileActivity,
656
883
  resolveLocalizedText,
657
- resolvePetCharacter
884
+ resolvePetCharacter,
885
+ upsertFileActivityContent
658
886
  };
659
887
  //# sourceMappingURL=index.js.map