{"context":{"domain":"pliskin"},"layers":{"ApplicationLayer":{"reference":"ApplicationLayer","availableInstances":[{"reference":"ComponentsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@DataSet","reference":"SystemsDataSet","params":{"filter":{"domain":"data2"},"pagination":{"size":1},"datasource":{"component":"data2-core-types@ProcessReference","params":{"reference":"SystemsDataSource"}}}},{"reference":"ExternalComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"SystemsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"5e3b796d6228227ca637d0f4","name":"data2","domain":"data2","organization":"62292184611f480b3191c37c","visibility":"public","updatedAt":"2026-07-27T14:19:36.810Z"}]}},{"reference":"OrganizationsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"DataComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@DataSet","reference":"OneFileComponentInstancesDataSet","params":{"pagination":{"size":1},"master":{"dataset":{"component":"data2-core-types@ProcessReference","params":{"reference":"SystemsDataSet"}},"localField":"system","masterField":"_id"},"datasource":{"component":"data2-core-types@ProcessReference","params":{"reference":"FileComponentInstancesDataSource"}}}},{"reference":"ApplicationsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"ComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"ServiceComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@Data2TableDataSource","reference":"FileComponentInstancesDataSource","params":{"table":"fileComponentInstances","schema":[{"component":"data2-core-types@Field","params":{"key":"component","title":"Component","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"system","title":"System","component":"data2-core-primitives@ObjectId"}},{"component":"data2-core-types@Field","params":{"key":"displayName","title":"Display Name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"params","title":"Params","component":"data2-core-primitives@Object"}},{"component":"data2-core-types@Field","params":{"key":"reference","title":"Reference","component":"data2-core-primitives@String"}}]}},{"component":"data2-core@MemoryDataSource","reference":"EmptyDataSource","params":{"initialData":[]}},{"reference":"ComponentsDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"UserComponentsDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"DataComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ServiceComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ExternalComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ApplicationsDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}}],"processesParams":{}},"HostApplicationLayer":{"reference":"HostApplicationLayer","availableInstances":[{"_id":"5f15ff190528b92601890f71","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"SystemsTableDataSource"}},"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"domain"}}},"pk":"_id","fields":[{"component":"data2-core-types@FieldReference","params":{"key":"_id"}},{"component":"data2-core-types@FieldReference","params":{"key":"name"}},{"component":"data2-core-types@FieldReference","params":{"key":"domain"}},{"component":"data2-core-types@FieldReference","params":{"key":"visibility"}},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"customDomains"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization._id"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization.name"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization.billingStatus"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization.publicTrial.active"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"settings.defaultAccessPolicy"}}},"break":true}],"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}},"staticPagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}},"policies":[{"component":"data2-core-auth@Policy","params":{"allow":{"params":{"actions":[{"params":{"components":[{"params":{"query":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$params.query"}}}},"field":{"component":"data2-core-primitives@String","params":{"content":"_id"}},"fieldType":"string"},"component":"data2@7KkQq0vK4a7D2gg6IVJT7"},{"params":{"query":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$params.query"}}}},"field":{"component":"data2-core-primitives@String","params":{"content":"domain"}},"fieldType":"string"},"component":"data2@7KkQq0vK4a7D2gg6IVJT7"},{"params":{"query":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$params.query"}}}},"field":{"component":"data2-core-primitives@String","params":{"content":"customDomains"}},"fieldType":"string"},"component":"data2@7KkQq0vK4a7D2gg6IVJT7"}]},"component":"data2-core-logical-operators@Or"}]},"component":"data2-core-flow@Series"}}}]},"reference":"SystemsDataSet","updatedAt":"2026-08-07T21:51:24.037Z","createdAt":"2020-07-20T20:31:21.838Z"},{"_id":"5f1601ce0528b92601890f7c","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":1000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentsTableDataSource"}},"sort":{"params.package":1,"params.component":1},"pk":"_id","autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"staticFilter":{"system":{"exists":{"params":{"content":false},"component":"data2-core-primitives@Boolean"}}},"filter":{"system":{"exists":{"params":{"content":false},"component":"data2-core-primitives@Boolean"}}}},"reference":"ComponentsDataSet","updatedAt":"2025-11-05T19:37:01.935Z","createdAt":"2020-07-20T20:42:54.898Z"},{"_id":"5f9041dbc8da12be8b94aea4","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":2000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentsTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"UserComponentsDataSet","updatedAt":"2025-11-06T21:06:58.095Z","createdAt":"2020-07-20T20:44:09.350Z"},{"_id":"65d8c4fabc9dbb8f94de8d53","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ExternalComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ExternalComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:23.742Z","createdAt":"2024-02-23T16:17:01.816Z"},{"reference":"SystemsTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"69f8a1f302514a1d6508bdbc","name":"pliskin","domain":"pliskin","visibility":"public","settings":{"defaultAccessPolicy":"private"},"updatedAt":"2026-08-26T20:21:41.365Z","createdAt":"2026-05-04T13:41:07.247Z"}]}},{"reference":"ComponentsTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"5f52a278a575399a45d239b4","component":"data2-core-types@Component","params":{"package":"data2-core-primitives","component":"Router","interactions":{"component":"data2-core-types@FieldSet","params":{"fields":{"goBack":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-types@Function"}},"definition":{"component":"data2-core-functions@Function","params":{"body":{"preventEvaluation":true,"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@This","params":{}},"prop":"history.goBack","args":[]}}}},"icon":{"component":"data2-core-primitives@String","params":{"content":"arrow-left"}},"visibility":"public"}},"goTo":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"definition":{"component":"data2-core-functions@Function","params":{"body":{"preventEvaluation":true,"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@This","params":{}},"prop":"history.push","args":[{"component":"data2-core-types@Reference","params":{"reference":"url"}},{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"preserveQuery"}}}}]}},"parameters":[{"component":"data2-core-primitives@String","params":{"content":"url"}},{"component":"data2-core-primitives@String","params":{"content":"preserveQuery"}}]},"break":true},"icon":{"component":"data2-core-primitives@String","params":{"content":"share"}},"visibility":"public","arguments":[{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Path to route"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Path to redirect user"}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2-core-types@ComponentParameter"},{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Boolean"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Preserve Query"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Preserve query string parameters  preserve query parameters on navigating."}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2-core-types@ComponentParameter"}]}},"open":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-types@Function"}},"definition":{"component":"data2-core-functions@Function","params":{"body":{"preventEvaluation":true,"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@This","params":{}},"prop":"history.push","args":[{"pathname":{"component":"data2-core-types@Reference","params":{"reference":"value"}}}]}},"parameters":["value"]}},"icon":{"component":"data2-core-primitives@String","params":{"content":"share"}},"visibility":"public","arguments":[{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Link to open"}},"description":{"component":"data2-core-primitives@String","params":{"content":""}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2-core-types@ComponentParameter"},{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Target"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Where to open the link"}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"oneOf":[{"params":{"content":"_blank"},"component":"data2-core-primitives@String"},{"params":{"content":"_self"},"component":"data2-core-primitives@String"},{"params":{"content":"_parent"},"component":"data2-core-primitives@String"},{"params":{"content":"_top"},"component":"data2-core-primitives@String"}]},"component":"data2-core-types@ComponentParameter"}]}},"close":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-types@Function"}},"definition":{"component":"data2-core-functions@Function","params":{"body":{"preventEvaluation":true,"component":"data2-core-types@Getter","params":{"module":{"params":{},"component":"data2-core-web@Window"},"prop":"close"}},"parameters":["value"]}},"icon":{"component":"data2-core-primitives@String","params":{"content":"times"}},"visibility":"public","arguments":[{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Link to open"}},"description":{"component":"data2-core-primitives@String","params":{"content":""}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2-core-types@ComponentParameter"},{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Target"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Where to open the link"}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"oneOf":[{"params":{"content":"_blank"},"component":"data2-core-primitives@String"},{"params":{"content":"_self"},"component":"data2-core-primitives@String"},{"params":{"content":"_parent"},"component":"data2-core-primitives@String"},{"params":{"content":"_top"},"component":"data2-core-primitives@String"}]},"component":"data2-core-types@ComponentParameter"}],"description":{"component":"data2-core-primitives@String","params":{"content":"Closes a window that was opened via router.open."}}}}}}}}},{"_id":"620d28658271aa4129919d89","component":"data2-core-types@Component","params":{"package":"data2-interface-services","component":"DeviceController","interactions":{"params":{"fields":{"postMessage":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":"data2-core-primitives@String","title":{"component":"data2-core-primitives@String","params":{"content":"data"}}}}]},"component":"data2-core-types@ComponentParameter"},"print":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Object"}},"flat":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"parameters":{"zoom":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Number"}},"title":{"component":"data2-core-primitives@String","params":{"content":"zoom"}},"visibility":"public"}}},"visibility":"public"},"component":"data2-core-types@ComponentParameter"}],"visibility":"public"},"component":"data2-core-types@ComponentParameter"},"share":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}}},"component":"data2-core-types@ComponentParameter"},"clipboard.copy":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}}}}]},"component":"data2-core-types@ComponentParameter"},"clipboard.paste":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}}}}]},"component":"data2-core-types@ComponentParameter"},"download":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"public","arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Filename"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Content"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Object"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Options"}},"parameters":{"params":{"fields":{"type":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Mimetype"}}}}}},"component":"data2-core-types@FieldSet"}}}]},"component":"data2-core-types@ComponentParameter"},"downloadUrl":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"public","arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Filename"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Url"}}}}]},"component":"data2-core-types@ComponentParameter"},"promptFiles":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":"data2-core-primitives@Object","flat":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"parameters":{"params":{"fields":{"multiple":{"component":"data2-core-types@ComponentParameter","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Multiple"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Whether or not to allow selecting multiple files"}},"component":"data2-core-primitives@Boolean"}},"acceptedFormats":{"component":"data2-core-types@ComponentParameter","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Accepted Formats"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Accepted file formats"}},"component":"data2-core-primitives@String","list":{"component":"data2-core-primitives@Boolean","params":{"content":true}}}},"timeout":{"component":"data2-core-types@ComponentParameter","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Timeout"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Max milliseconds to wait for file upload"}},"component":"data2-core-primitives@Number"}}}},"component":"data2-core-types@FieldSet"}}}],"visibility":"public"},"component":"data2-core-types@ComponentParameter"},"meetingRecord":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"public","definition":{"params":{"actions":[{"params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"meeting"}},"script":{"component":"data2-core-primitives@String","params":{"content":"(function() {\n  let mediaRecorder;\n  let audioChunks = [];\n  let combinedStream;\n  let audioContext;\n  \n  window.meetingCapture = async function() {\n    try {\n      // Solicitar acesso ao áudio da guia (e vídeo, que será ignorado depois)\n      const tabStream = await navigator.mediaDevices.getDisplayMedia({ \n        video: true, // Necessário para alguns navegadores\n        audio: true\n      });\n      \n      // Remover a trilha de vídeo\n      const tabAudioTrack = tabStream.getAudioTracks()[0];\n      \n      // Solicitar acesso ao microfone\n      const micStream = await navigator.mediaDevices.getUserMedia({ audio: true });\n      const micAudioTrack = micStream.getAudioTracks()[0];\n      \n      // Criar um novo MediaStream com ambas as trilhas de áudio\n      combinedStream = new MediaStream([tabAudioTrack, micAudioTrack]);\n      \n      // Criar um contexto de áudio para misturar os streams\n      audioContext = new AudioContext();\n      const destination = audioContext.createMediaStreamDestination();\n      \n      // Conectar a trilha de áudio da guia\n      const tabSource = audioContext.createMediaStreamSource(new MediaStream([tabAudioTrack]));\n      tabSource.connect(destination);\n      \n      // Conectar a trilha de áudio do microfone\n      const micSource = audioContext.createMediaStreamSource(new MediaStream([micAudioTrack]));\n      micSource.connect(destination);\n      \n      // Iniciar gravação com o stream misturado\n      mediaRecorder = new MediaRecorder(destination.stream);\n      audioChunks = [];\n      mediaRecorder.ondataavailable = (e) => audioChunks.push(e.data);\n      mediaRecorder.start();\n      \n      console.log('Gravação iniciada. Chame meetingCaptureStop() para finalizar.');\n    } catch (error) {\n      console.error('Erro ao iniciar a captura:', error);\n    }\n  };\n  \n  window.meetingCaptureStop = function() {\n    return new Promise((resolve, reject) => {\n      if (!mediaRecorder) {\n        reject('Nenhuma gravação em andamento.');\n        return;\n      }\n      \n      mediaRecorder.onstop = () => {\n        const audioBlob = new Blob(audioChunks, { type: 'audio/webm' });\n        combinedStream.getTracks().forEach(track => track.stop());\n        audioContext.close();\n        \n        resolve(audioBlob);\n        console.log('Gravação finalizada. O arquivo de áudio está pronto para upload.');\n      };\n      \n      mediaRecorder.stop();\n    });\n  };\n})();"}}},"component":"data2-core-web@Script"},{"component":"data2-core-types@Getter","params":{"module":{"params":{},"component":"data2-core-web@Window"},"prop":{"component":"data2-core-primitives@String","params":{"content":"meetingCapture"}}}}]},"component":"data2-core-flow@Series"}},"component":"data2-core-types@ComponentParameter"},"meetingRecordStop":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"public","arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Filename"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Content"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Object"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Options"}},"parameters":{"params":{"fields":{"type":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Mimetype"}}}}}},"component":"data2-core-types@FieldSet"}}}],"definition":{"params":{"actions":[{"component":"data2-core-types@Getter","params":{"module":{"params":{},"component":"data2-core-web@Window"},"prop":{"component":"data2-core-primitives@String","params":{"content":"meetingCaptureStop"}}}}]},"component":"data2-core-flow@Series"}},"component":"data2-core-types@ComponentParameter"},"notify":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"private","arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":"data2-core-primitives@Object","parameters":{"title":{"params":{"component":"data2-core-primitives@String","index":{"component":"data2-core-primitives@Number","params":{"content":0}},"title":{"component":"data2-core-primitives@String","params":{"content":"title"}}},"component":"data2-core-types@ComponentParameter"},"sound":{"params":{"component":"data2-core-types@FileComponentUrlReference","index":{"component":"data2-core-primitives@Number","params":{"content":1}},"title":{"component":"data2-core-primitives@String","params":{"content":"sound"}}},"component":"data2-core-types@ComponentParameter"}},"flat":{"component":"data2-core-primitives@Boolean","params":{"content":true}}}}]},"component":"data2-core-types@ComponentParameter"}}},"component":"data2-core-types@FieldSet"}}},{"_id":"6a73829c294e8683da4d4999","component":"data2-core-types@Component","system":"69f8a1f302514a1d6508bdbc","params":{"extends":"data2-core-primitives@Block","component":"uq4OwTFrsotXl9AMyRaPU","package":"pliskin","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const STATUS_COLS = [\n  { key: 'todo', label: 'A Fazer' },\n  { key: 'doing', label: 'Em Andamento' },\n  { key: 'done', label: 'Concluído' },\n  { key: 'blocked', label: 'Bloqueado' }\n];\n\nconst PRIORITY_LABEL = { high: 'Alta', medium: 'Média', low: 'Baixa' };\n\nfunction esc(v) {\n  return String(v == null ? '' : v).replace(/[&<>\"']/g, function (c) {\n    return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' }[c];\n  });\n}\n\nfunction fmtDate(iso) {\n  if (!iso) return '—';\n  const d = new Date(iso);\n  if (isNaN(d.getTime())) return '—';\n  return d.toLocaleString('pt-BR', { day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit' });\n}\n\nfunction taskCard(t) {\n  const pr = (t.priority || '').toLowerCase();\n  const prLabel = PRIORITY_LABEL[pr] || (t.priority ? esc(t.priority) : '—');\n  return `<div class=\"kcard\" data-key=\"${esc(t._id)}\">\n    <div class=\"kcard-title\">${esc(t.title || 'Sem título')}</div>\n    <div class=\"kcard-meta\">\n      <span class=\"kslug\">${esc(t.projectSlug || '—')}</span>\n      <span class=\"priority-pill pr-${esc(pr || 'none')}\">${prLabel}</span>\n    </div>\n  </div>`;\n}\n\nfunction columnHtml(col) {\n  const body = col.items.length\n    ? col.items.map(taskCard).join('')\n    : `<div class=\"kempty\">Nenhuma tarefa</div>`;\n  return `<div class=\"kcol\" data-status=\"${col.key}\">\n    <div class=\"kcol-head\">\n      <span class=\"kdot dot-${col.key}\"></span>\n      <span class=\"kcol-label\">${col.label}</span>\n      <span class=\"kcol-count\">${col.items.length}</span>\n    </div>\n    <div class=\"kcol-body\">${body}</div>\n  </div>`;\n}\n\nfunction timelineRow(ev) {\n  return `<div class=\"trow\" data-key=\"${esc(ev.id)}\">\n    <div class=\"tleft\">\n      <span class=\"ttype ${ev.type}\">${ev.label}</span>\n      <div class=\"tstage\">${esc(ev.stage || '—')}</div>\n    </div>\n    <div class=\"ttext\">${esc(ev.text || '(sem descrição)')}</div>\n    <div class=\"tmeta\">\n      <div>${esc(ev.role || '—')}</div>\n      <div>${fmtDate(ev.createdAt)}</div>\n    </div>\n  </div>`;\n}\n\nfunction computeGraphData(humans, agents, sessions, projects, specialists) {\n  const sessByAgent = {};\n  sessions.forEach(function (s) {\n    if (s.agentSlug) { (sessByAgent[s.agentSlug] = sessByAgent[s.agentSlug] || []).push(s); }\n  });\n  const specByProject = {};\n  specialists.forEach(function (s) {\n    if (s.projectSlug) { (specByProject[s.projectSlug] = specByProject[s.projectSlug] || []).push(s); }\n  });\n\n  const humanNodes = humans.map(function (h) {\n    return { id: 'h:' + h.slug, title: h.name || h.slug, sub: (h.role || '').toUpperCase() };\n  });\n  const agentNodes = agents.map(function (a) {\n    return { id: 'a:' + a.agentSlug, title: a.agentSlug, sub: (a.status || '').toUpperCase(), ownerHumanSlug: a.ownerHumanSlug };\n  });\n\n  const projSlugsWithAgent = {};\n  agentNodes.forEach(function (a) {\n    (sessByAgent[a.title] || []).forEach(function (s) {\n      if (s.projectSlug) projSlugsWithAgent[s.projectSlug] = true;\n    });\n  });\n\n  const projectNodes = [];\n  const seenProjSlug = {};\n  projects.forEach(function (p) {\n    projectNodes.push({ id: 'p:' + p.slug, title: p.name || p.slug, sub: (p.currentStage || p.status || '').toUpperCase(), slug: p.slug, registered: true });\n    seenProjSlug[p.slug] = true;\n  });\n  Object.keys(projSlugsWithAgent).forEach(function (slug) {\n    if (!seenProjSlug[slug]) {\n      projectNodes.push({ id: 'p:' + slug, title: slug, sub: 'NÃO REGISTRADO', slug: slug, registered: false });\n      seenProjSlug[slug] = true;\n    }\n  });\n\n  const edgesHA = [];\n  agentNodes.forEach(function (a) {\n    const hid = 'h:' + a.ownerHumanSlug;\n    if (humanNodes.some(function (h) { return h.id === hid; })) edgesHA.push({ from: hid, to: a.id });\n  });\n\n  const edgesAP = [];\n  const seenAP = {};\n  agentNodes.forEach(function (a) {\n    const slugs = {};\n    (sessByAgent[a.title] || []).forEach(function (s) { if (s.projectSlug) slugs[s.projectSlug] = true; });\n    Object.keys(slugs).forEach(function (slug) {\n      const key = a.id + '->p:' + slug;\n      if (!seenAP[key]) { seenAP[key] = true; edgesAP.push({ from: a.id, to: 'p:' + slug }); }\n    });\n  });\n\n  const specialistNodes = [];\n  const edgesPS = [];\n  projectNodes.forEach(function (p) {\n    const list = specByProject[p.slug] || [];\n    if (list.length === 0) {\n      const id = 'sX:' + p.slug;\n      specialistNodes.push({ id: id, title: 'Nenhum especialista', sub: '—', placeholder: true });\n      edgesPS.push({ from: p.id, to: id });\n    } else {\n      list.forEach(function (s, i) {\n        const id = 's:' + p.slug + ':' + i;\n        specialistNodes.push({ id: id, title: s.name || s.slug, sub: (s.domain || '').toUpperCase() });\n        edgesPS.push({ from: p.id, to: id });\n      });\n    }\n  });\n\n  return {\n    humanNodes: humanNodes, agentNodes: agentNodes, projectNodes: projectNodes, specialistNodes: specialistNodes,\n    edgesHA: edgesHA, edgesAP: edgesAP, edgesPS: edgesPS\n  };\n}\n\nfunction buildGraphSvg(g) {\n  const tiers = [g.humanNodes, g.agentNodes, g.projectNodes, g.specialistNodes];\n  const tierLabels = ['HUMANO', 'AGENTE', 'PROJETO', 'ESPECIALISTA'];\n  const TIER_X = [10, 280, 550, 820];\n  const ROW_H = 68;\n  const TOP = 46;\n  const positions = {};\n  let maxRows = 1;\n  tiers.forEach(function (nodes, ti) {\n    maxRows = Math.max(maxRows, nodes.length);\n    nodes.forEach(function (n, i) {\n      positions[n.id] = { x: TIER_X[ti], y: TOP + i * ROW_H };\n    });\n  });\n  const svgH = TOP + maxRows * ROW_H + 16;\n  const svgW = 1080;\n\n  function nodeRect(n) {\n    const pos = positions[n.id];\n    if (!pos) return '';\n    let cls = 'gnode';\n    if (n.placeholder) cls += ' ghost';\n    if (n.registered === false) cls += ' danger';\n    return `<g class=\"${cls}\" transform=\"translate(${pos.x},${pos.y})\" data-key=\"${esc(n.id)}\">\n      <rect width=\"220\" height=\"52\" rx=\"4\"></rect>\n      <text x=\"12\" y=\"21\" class=\"gtitle\">${esc(n.title)}</text>\n      <text x=\"12\" y=\"38\" class=\"gsub\">${esc(n.sub || '')}</text>\n    </g>`;\n  }\n\n  function edgePath(e) {\n    const a = positions[e.from], b = positions[e.to];\n    if (!a || !b) return '';\n    const x1 = a.x + 220, y1 = a.y + 26, x2 = b.x, y2 = b.y + 26;\n    const mx = (x1 + x2) / 2;\n    return `<path d=\"M${x1},${y1} C${mx},${y1} ${mx},${y2} ${x2},${y2}\" class=\"gedge\"></path>`;\n  }\n\n  const allNodes = [].concat(g.humanNodes, g.agentNodes, g.projectNodes, g.specialistNodes);\n  const allEdges = [].concat(g.edgesHA, g.edgesAP, g.edgesPS);\n\n  const labelsHtml = tierLabels.map(function (lab, ti) {\n    return `<text x=\"${TIER_X[ti]}\" y=\"16\" class=\"gtierlabel\">${esc(lab)}</text>`;\n  }).join('');\n\n  return `<svg viewBox=\"0 0 ${svgW} ${svgH}\" width=\"100%\" height=\"${svgH}\" class=\"graph-svg\">\n    ${labelsHtml}\n    ${allEdges.map(edgePath).join('')}\n    ${allNodes.map(nodeRect).join('')}\n  </svg>`;\n}\n\nfunction chipHtml(n) {\n  let cls = 'gchip';\n  if (n.placeholder) cls += ' ghost';\n  if (n.registered === false) cls += ' danger';\n  return `<div class=\"${cls}\" data-key=\"${esc(n.id)}\">\n    <div class=\"gchip-title\">${esc(n.title)}</div>\n    ${n.sub ? `<div class=\"gchip-sub\">${esc(n.sub)}</div>` : ''}\n  </div>`;\n}\n\nfunction graphMobileHtml(g) {\n  const blocks = [\n    ['HUMANO', g.humanNodes],\n    ['AGENTE', g.agentNodes],\n    ['PROJETO', g.projectNodes],\n    ['ESPECIALISTA', g.specialistNodes]\n  ].map(function (pair) {\n    const label = pair[0], nodes = pair[1];\n    const chips = nodes.length ? nodes.map(chipHtml).join('') : `<div class=\"gchip ghost\"><div class=\"gchip-title\">Nenhum</div></div>`;\n    return `<div class=\"gtier-block\">\n      <div class=\"gtier-label\">${label}</div>\n      <div class=\"gtier-chips\">${chips}</div>\n    </div>`;\n  });\n  return `<div class=\"graph-mobile\">${blocks.join('<div class=\"gtier-arrow\">↓</div>')}</div>`;\n}\n\nexport default {\n  css: `\n@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=IBM+Plex+Sans:wght@400;500;600;700&display=swap');\n:host{display:block;height:100%;width:100%;}\n.linadmin{height:100%;width:100%;}\n*{box-sizing:border-box;}\n.page{\n  height:100vh; overflow-y:auto; -webkit-overflow-scrolling:touch;\n  background:var(--bg); color:var(--text);\n  font-family:'IBM Plex Sans',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Arial,sans-serif;\n  font-size:14px; line-height:1.5;\n  --bg:#14151a; --surface:#1b1d24; --surface2:#22252d; --border:#2f323b;\n  --text:#e7e9ee; --muted:#8b909c; --faint:#5c606b;\n  --accent:#e2a640; --danger:#d6524a; --success:#3fa66a; --todo:#6b7280;\n  padding: 28px 40px 60px;\n}\n.topbar{display:flex;align-items:flex-start;justify-content:space-between;gap:24px;margin-bottom:32px;flex-wrap:wrap;}\n.titleblock h1{font-size:22px;font-weight:700;margin:0 0 4px;letter-spacing:-.01em;}\n.subtitle{margin:0;color:var(--muted);font-size:12px;font-family:'IBM Plex Mono',ui-monospace,monospace;}\n.scope-badge{background:var(--surface2);border:1px solid var(--accent);color:var(--accent);font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:11px;letter-spacing:.02em;padding:8px 14px;border-radius:4px;white-space:nowrap;}\n.section{margin-bottom:40px;}\n.section-head{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:14px;}\n.section-head h2{font-size:15px;font-weight:600;margin:0;text-transform:uppercase;letter-spacing:.04em;color:var(--text);}\n.section-meta{font-size:12px;color:var(--faint);font-family:'IBM Plex Mono',ui-monospace,monospace;}\n.kanban-board{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;}\n.kcol{display:flex;flex-direction:column;height:560px;background:var(--surface);border:1px solid var(--border);border-radius:4px;overflow:hidden;}\n.kcol-head{padding:12px 14px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:8px;flex-shrink:0;}\n.kdot{width:8px;height:8px;border-radius:50%;flex-shrink:0;}\n.dot-todo{background:var(--todo);} .dot-doing{background:var(--accent);} .dot-done{background:var(--success);} .dot-blocked{background:var(--danger);}\n.kcol-label{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.03em;flex:1;}\n.kcol-count{font-size:11px;color:var(--muted);font-family:'IBM Plex Mono',ui-monospace,monospace;}\n.kcol-body{flex:1;overflow-y:auto;padding:10px;display:flex;flex-direction:column;gap:8px;}\n.kcard{background:var(--surface2);border:1px solid var(--border);border-radius:4px;padding:10px 12px;}\n.kcard-title{font-size:13px;color:var(--text);margin-bottom:8px;line-height:1.4;}\n.kcard-meta{display:flex;align-items:center;justify-content:space-between;font-size:11px;font-family:'IBM Plex Mono',ui-monospace,monospace;}\n.kslug{color:var(--muted);}\n.priority-pill{text-transform:uppercase;letter-spacing:.03em;font-size:10px;}\n.pr-high{color:var(--danger);} .pr-medium{color:var(--accent);} .pr-low{color:var(--muted);} .pr-none{color:var(--faint);}\n.kempty{color:var(--faint);font-size:12px;font-style:italic;text-align:center;padding:20px 8px;}\n.timeline-list{background:var(--surface);border:1px solid var(--border);border-radius:4px;max-height:480px;overflow-y:auto;}\n.trow{display:grid;grid-template-columns:110px 1fr 150px;gap:16px;padding:14px 18px;border-bottom:1px solid var(--border);}\n.trow:last-child{border-bottom:none;}\n.ttype{display:inline-block;font-size:10px;text-transform:uppercase;letter-spacing:.04em;padding:2px 7px;border-radius:3px;font-family:'IBM Plex Mono',ui-monospace,monospace;margin-bottom:6px;}\n.ttype.decisao{color:var(--accent);border:1px solid var(--accent);}\n.ttype.artefato{color:var(--muted);border:1px solid var(--border);}\n.tstage{font-size:11px;color:var(--faint);}\n.ttext{font-size:13px;color:var(--text);line-height:1.55;}\n.tmeta{font-size:11px;color:var(--muted);text-align:right;font-family:'IBM Plex Mono',ui-monospace,monospace;line-height:1.6;}\n.graph-wrap{background:var(--surface);border:1px solid var(--border);border-radius:4px;padding:20px;overflow-x:auto;}\n.graph-svg{display:block;}\n.gnode rect{fill:var(--surface2);stroke:var(--border);stroke-width:1;}\n.gnode.ghost rect{fill:none;stroke:var(--faint);stroke-dasharray:4 3;}\n.gnode.danger rect{stroke:var(--danger);}\n.gtitle{fill:var(--text);font-size:12px;font-family:'IBM Plex Sans',sans-serif;font-weight:600;}\n.gsub{fill:var(--muted);font-size:10px;font-family:'IBM Plex Mono',ui-monospace,monospace;}\n.gnode.ghost .gtitle, .gnode.ghost .gsub{fill:var(--faint);font-style:italic;}\n.gedge{fill:none;stroke:var(--border);stroke-width:1.5;}\n.gtierlabel{fill:var(--faint);font-size:10px;text-transform:uppercase;letter-spacing:.05em;font-family:'IBM Plex Mono',ui-monospace,monospace;}\n.graph-mobile{display:flex;flex-direction:column;align-items:center;gap:4px;}\n.gtier-block{width:100%;}\n.gtier-label{font-size:10px;text-transform:uppercase;letter-spacing:.05em;color:var(--faint);font-family:'IBM Plex Mono',ui-monospace,monospace;margin-bottom:8px;text-align:center;}\n.gtier-chips{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;}\n.gchip{background:var(--surface2);border:1px solid var(--border);border-radius:4px;padding:8px 12px;min-width:120px;}\n.gchip.ghost{background:none;border-style:dashed;border-color:var(--faint);}\n.gchip.danger{border-color:var(--danger);}\n.gchip-title{font-size:12px;color:var(--text);font-weight:600;}\n.gchip-sub{font-size:10px;color:var(--muted);font-family:'IBM Plex Mono',ui-monospace,monospace;margin-top:2px;}\n.gtier-arrow{color:var(--faint);font-size:14px;margin:2px 0;text-align:center;}\n.foot{margin-top:8px;padding-top:20px;border-top:1px solid var(--border);color:var(--faint);font-size:11px;font-family:'IBM Plex Mono',ui-monospace,monospace;text-align:center;}\n.loading{padding:60px;text-align:center;color:var(--muted);font-family:'IBM Plex Mono',ui-monospace,monospace;}\n@media (max-width:1024px){ .kanban-board{grid-template-columns:repeat(2,1fr);} }\n@media (max-width:700px){\n  .page{padding:20px 16px 40px;}\n  .topbar{flex-direction:column;align-items:flex-start;}\n  .scope-badge{white-space:normal;max-width:100%;}\n  .kanban-board{grid-template-columns:1fr;}\n  .kcol{height:280px;}\n  .trow{grid-template-columns:1fr;gap:6px;}\n  .tmeta{text-align:left;}\n}\n`,\n\n  async mounted(d2) {\n    try {\n      const names = ['tasksDs', 'decisionsDs', 'artifactsDs', 'agentsDs', 'sessionsDs', 'projectsDs', 'specialistsDs', 'humansDs'];\n      await Promise.all(names.map(function (n) {\n        const h = d2.data(n);\n        return h && h.refresh ? h.refresh() : Promise.resolve();\n      }));\n    } catch (e) {\n      d2.log('lean-admin mounted refresh error', e && e.message);\n    }\n    d2.setState({ ready: true });\n  },\n\n  render(d2) {\n    if (!d2.state.ready) {\n      return `<div class=\"linadmin\"><div class=\"page\"><div class=\"loading\">Carregando dados…</div></div></div>`;\n    }\n\n    const tasks = d2.data('tasksDs').records();\n    const decisions = d2.data('decisionsDs').records();\n    const artifacts = d2.data('artifactsDs').records();\n    const agents = d2.data('agentsDs').records();\n    const sessions = d2.data('sessionsDs').records();\n    const projects = d2.data('projectsDs').records();\n    const specialists = d2.data('specialistsDs').records();\n    const humans = d2.data('humansDs').records();\n\n    const cols = STATUS_COLS.map(function (col) {\n      return Object.assign({}, col, { items: tasks.filter(function (t) { return t.status === col.key; }) });\n    });\n    const kanbanHtml = cols.map(columnHtml).join('');\n\n    const timeline = [].concat(\n      decisions.map(function (d) { return { id: d._id, type: 'decisao', label: 'Decisão', text: d.decision, stage: d.stage, role: d.decidedByRole, createdAt: d.createdAt }; }),\n      artifacts.map(function (a) { return { id: a._id, type: 'artefato', label: 'Artefato', text: a.title, stage: a.stage, role: a.createdByRole, createdAt: a.createdAt }; })\n    ).sort(function (a, b) { return new Date(b.createdAt || 0) - new Date(a.createdAt || 0); });\n\n    const timelineHtml = timeline.length ? timeline.map(timelineRow).join('') : `<div class=\"kempty\">Sem eventos registrados</div>`;\n\n    const gdata = computeGraphData(humans, agents, sessions, projects, specialists);\n    const width = (d2.root && d2.root.clientWidth) || (typeof window !== 'undefined' ? window.innerWidth : 1280);\n    const isNarrow = width < 720;\n    const graphHtml = isNarrow ? graphMobileHtml(gdata) : buildGraphSvg(gdata);\n\n    return `<div class=\"linadmin\"><div class=\"page\">\n    <div class=\"topbar\">\n      <div class=\"titleblock\">\n        <h1>Lean Inception — Admin</h1>\n        <p class=\"subtitle\">lean-inception-os · pliskin</p>\n      </div>\n      <div class=\"scope-badge\">Visão Super-Admin — todos os humanos e projetos</div>\n    </div>\n\n    <div class=\"section\">\n      <div class=\"section-head\"><h2>Tarefas</h2><span class=\"section-meta\">${tasks.length} tarefa(s)</span></div>\n      <div class=\"kanban-board\">${kanbanHtml}</div>\n    </div>\n\n    <div class=\"section\">\n      <div class=\"section-head\"><h2>Linha do tempo</h2><span class=\"section-meta\">${timeline.length} evento(s)</span></div>\n      <div class=\"timeline-list\">${timelineHtml}</div>\n    </div>\n\n    <div class=\"section\">\n      <div class=\"section-head\"><h2>Hierarquia</h2><span class=\"section-meta\">Humano → Agente → Projeto → Especialista</span></div>\n      <div class=\"graph-wrap\">${graphHtml}</div>\n    </div>\n\n    <div class=\"foot\">Lean Inception OS — dados ao vivo (lean-tasks, lean-decisions, lean-stage-artifacts, lean-agents, lean-agent-sessions, lean-projects, lean-specialists, lean-humans)</div>\n  </div></div>`;\n  }\n};\n"}},"tasksDs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tasksDs"}}}},"decisionsDs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"decisionsDs"}}}},"artifactsDs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"artifactsDs"}}}},"agentsDs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"agentsDs"}}}},"sessionsDs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"sessionsDs"}}}},"projectsDs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"projectsDs"}}}},"specialistsDs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"specialistsDs"}}}},"humansDs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"humansDs"}}}}}}}}}},{"_id":"6a7404829b80399cc1ea7a68","component":"data2-core-types@Component","system":"69f8a1f302514a1d6508bdbc","params":{"extends":"data2-core-primitives@Block","component":"flightMcpChat","package":"pliskin","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n    .wrap{display:flex;flex-direction:column;height:100%;width:100%;font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;background:#0d0d12}\n    .log{flex:1;overflow:auto;display:flex;flex-direction:column;gap:10px;padding:16px}\n    .msg{max-width:78%;padding:10px 14px;border-radius:14px;font-size:14px;line-height:1.45;white-space:pre-wrap}\n    .me{align-self:flex-end;background:#3ed47e;color:#062b16}\n    .ai{align-self:flex-start;background:#1c1c24;color:#eee}\n    .answer{white-space:pre-wrap}\n    .steps-list{display:flex;flex-direction:column;gap:4px;margin-bottom:6px}\n    .step{font-size:12px;opacity:.8;color:#8fe6ac}\n    details.steps{margin-bottom:6px}\n    details.steps summary{cursor:pointer;font-size:11px;opacity:.6;list-style:none}\n    details.steps summary::-webkit-details-marker{display:none}\n    details.steps[open] summary{margin-bottom:4px}\n    .row{display:flex;gap:8px;padding:12px;border-top:1px solid #22222c;background:#0d0d12}\n    .row input{flex:1;padding:10px 12px;border-radius:10px;border:1px solid #33333f;background:#16161d;color:#fff;font-size:14px}\n    .row input:focus{outline:none;border-color:#3ed47e}\n    .row button{padding:10px 18px;border-radius:10px;border:none;background:#3ed47e;color:#062b16;font-weight:600;cursor:pointer;font-size:14px}\n    .row button:disabled{opacity:.5;cursor:default}\n    .typing{display:flex;gap:4px;padding:6px 2px}\n    .dot{width:6px;height:6px;border-radius:50%;background:#888;animation:blink 1.2s infinite}\n    .dot:nth-child(2){animation-delay:.2s}\n    .dot:nth-child(3){animation-delay:.4s}\n    @keyframes blink{0%,80%,100%{opacity:.2}40%{opacity:1}}\n    .empty{opacity:.55;padding:24px;text-align:center;font-size:13px;color:#ccc}\n  `,\n  render(d2){\n    const msgs = d2.state.messages || []\n    const busy = !!d2.state.busy\n    const bubbles = msgs.map(m => {\n      if (m.role === 'user') {\n        return `<div class=\"msg me\" data-key=\"${m.id}\">${esc(m.text)}</div>`\n      }\n      const steps = m.steps || []\n      const stepsHtml = steps.length ? `<div class=\"steps-list\">${steps.map(s => `<div class=\"step\">${esc(traceLine(s))}</div>`).join('')}</div>` : ''\n      if (m.pending) {\n        return `<div class=\"msg ai pending\" data-key=\"${m.id}\">${stepsHtml}<div class=\"typing\"><span class=\"dot\"></span><span class=\"dot\"></span><span class=\"dot\"></span></div></div>`\n      }\n      const collapsed = steps.length ? `<details class=\"steps\"><summary>Ver etapas (${steps.length})</summary>${stepsHtml}</details>` : ''\n      return `<div class=\"msg ai\" data-key=\"${m.id}\">${collapsed}<div class=\"answer\">${esc(m.text)}</div></div>`\n    }).join('')\n    const empty = (!msgs.length) ? `<div class=\"empty\">Pergunte algo como: \"voos de GRU pra JFK em 15 de setembro de 2026\"</div>` : ''\n    return `<div class=\"wrap\">\n      <div class=\"log\">${empty}${bubbles}</div>\n      <div class=\"row\">\n        <input class=\"in\" placeholder=\"Pergunte sobre voos...\" ${busy?'disabled':''}/>\n        <button class=\"send\" ${busy?'disabled':''}>${busy?'...':'Enviar'}</button>\n      </div>\n    </div>`\n  },\n  mounted(d2){\n    const send = async () => {\n      const el = d2.$('.in')\n      if (!el) return\n      const text = (el.value||'').trim()\n      if (!text || d2.state.busy) return\n      el.value = ''\n      const userMsg = { id: cid(), role:'user', text }\n      const pendingId = cid()\n      const pendingMsg = { id: pendingId, role:'assistant', pending: true, steps: [], text: '' }\n      d2.state.messages = [...(d2.state.messages||[]), userMsg, pendingMsg]\n      d2.state.busy = true\n      try {\n        const res = await d2.rush('flightMcpAgentLoop').stream({ query: text }, (u) => {\n          const step = (u && u.payload) ? u.payload : {}\n          d2.state.messages = (d2.state.messages||[]).map(m => m.id === pendingId ? { ...m, steps: [...(m.steps||[]), step] } : m)\n        })\n        const out = (res && res.data) ? res.data : res\n        const answer = (out && out.answer) ? out.answer : 'Desculpe, nao consegui obter uma resposta agora.'\n        d2.state.messages = (d2.state.messages||[]).map(m => m.id === pendingId ? { ...m, pending: false, text: answer } : m)\n      } catch (err) {\n        d2.state.messages = (d2.state.messages||[]).map(m => m.id === pendingId ? { ...m, pending: false, text: 'Erro ao consultar o agente: ' + (err && err.message ? err.message : String(err)) } : m)\n      } finally {\n        d2.state.busy = false\n      }\n    }\n    d2.on('.send','click', send)\n    d2.on('.in','keydown', (e)=>{ if (e.key === 'Enter') send() })\n  },\n  updated(d2){ const log = d2.$('.log'); if (log) log.scrollTop = log.scrollHeight },\n}\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;') }\nfunction cid(){ return 'c' + Math.random().toString(36).slice(2) }\nfunction traceLine(step){\n  const icons = { planning:'🤔', calling_tool:'🔧', tool_result:'✅', answering:'✍️' }\n  const icon = icons[step.status] || '•'\n  let label = step.status || ''\n  if (step.status === 'planning') label = 'Pensando...'\n  else if (step.status === 'calling_tool') label = 'Chamando ' + step.tool + '(' + summarizeArgs(step.tool, step.args) + ')...'\n  else if (step.status === 'tool_result') label = 'Resultado recebido de ' + step.tool\n  else if (step.status === 'answering') label = 'Escrevendo resposta...'\n  return icon + ' ' + label\n}\nfunction summarizeArgs(tool, args){\n  args = args || {}\n  if (tool === 'search_flights') return (args.origin||'?') + ' → ' + (args.destination||'?') + (args.depart_date ? ', ' + args.depart_date : '')\n  if (tool === 'search_calendar') return (args.origin||'?') + ' → ' + (args.destination||'?') + ', ' + (args.date||'')\n  if (tool === 'get_reference_data') return (args.type||'') + (args.query ? ': ' + args.query : '')\n  if (tool === 'discover_flights') return (args.type||'') + ' a partir de ' + (args.origin||'')\n  return ''\n}"}}}}}}}},{"_id":"6a740b5778c8cb1a2c2c315c","component":"data2-core-types@Component","system":"69f8a1f302514a1d6508bdbc","params":{"extends":"data2-core-primitives@Block","component":"mcpServersAdmin","package":"pliskin","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n    .wrap{display:flex;flex-direction:column;gap:20px;height:100%;width:100%;box-sizing:border-box;padding:24px;font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;background:#0d0d12;color:#eee;overflow:auto}\n    h1{font-size:18px;margin:0 0 4px 0;color:#fff}\n    .sub{font-size:12px;opacity:.6;margin-bottom:8px}\n    .list{display:flex;flex-direction:column;gap:10px}\n    .row{display:flex;align-items:center;gap:12px;background:#16161d;border:1px solid #26262f;border-radius:12px;padding:12px 14px}\n    .row .name{font-weight:600;font-size:14px;min-width:160px}\n    .row .url{font-size:12px;opacity:.65;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n    .badge{font-size:11px;padding:4px 10px;border-radius:999px;font-weight:600;cursor:pointer;border:none}\n    .badge.on{background:#1f4d34;color:#6ee7a0}\n    .badge.off{background:#3a2222;color:#e79a9a}\n    .iconbtn{background:none;border:1px solid #33333f;color:#ccc;border-radius:8px;padding:6px 10px;font-size:12px;cursor:pointer}\n    .iconbtn:hover{border-color:#3ed47e;color:#3ed47e}\n    .iconbtn.danger:hover{border-color:#e05c5c;color:#e05c5c}\n    .empty{opacity:.5;font-size:13px;padding:16px 0}\n    .formCard{background:#16161d;border:1px solid #26262f;border-radius:14px;padding:18px;display:flex;flex-direction:column;gap:10px}\n    .formCard h2{font-size:14px;margin:0 0 4px 0}\n    label{font-size:11px;opacity:.65;text-transform:uppercase;letter-spacing:.04em;margin-bottom:2px;display:block}\n    input, textarea, select{width:100%;box-sizing:border-box;padding:9px 11px;border-radius:8px;border:1px solid #33333f;background:#0d0d12;color:#fff;font-size:13px;font-family:inherit}\n    input:focus, textarea:focus, select:focus{outline:none;border-color:#3ed47e}\n    textarea{resize:vertical;min-height:90px;font-family:ui-monospace,monospace;font-size:11px}\n    .field{display:flex;flex-direction:column;gap:4px}\n    .row2{display:flex;gap:10px}\n    .row2 .field{flex:1}\n    .actions{display:flex;gap:8px;margin-top:6px;align-items:center}\n    .btn{padding:9px 16px;border-radius:8px;border:none;font-weight:600;font-size:13px;cursor:pointer}\n    .btn.primary{background:#3ed47e;color:#062b16}\n    .btn.ghost{background:transparent;color:#ccc;border:1px solid #33333f}\n    .btn.oauth{background:#5b8def;color:#06122b}\n    .btn:disabled{opacity:.5;cursor:default}\n    .hint{font-size:11px;opacity:.5;margin-top:-2px}\n    .err{color:#e79a9a;font-size:12px}\n    .topbar{display:flex;justify-content:flex-end}\n    .expired{padding:40px;text-align:center;opacity:.7;font-size:14px}\n    .callbackBox{background:#0d0d12;border:1px dashed #33333f;border-radius:8px;padding:8px 10px;font-size:11px;font-family:ui-monospace,monospace;word-break:break-all;color:#8fe6ac}\n    .status{font-size:11px;padding:3px 8px;border-radius:6px;margin-left:8px}\n    .status.connected{background:#1f4d34;color:#6ee7a0}\n    .status.disconnected{background:#3a2222;color:#e79a9a}\n    .status.unknown{background:#2a2a33;color:#999}\n  `,\n  render(d2){\n    const authed = d2.auth(d2.params.authStrategy).isAuthed\n    if (!authed) {\n      return `<div class=\"wrap\"><div class=\"expired\">Sessao expirada ou nao autenticada. Atualize a pagina para fazer login novamente.</div></div>`\n    }\n    const ds = d2.data('_ziKSflmzxQR07d7vxg66DataSet')\n    const rows = ds ? ds.records() : []\n    const draft = d2.state.draft\n    const status = d2.state.status || {}\n    const callbackUrl = (typeof window !== 'undefined' ? window.location.origin : '') + '/admin/oauth-callback'\n    const listHtml = rows.length ? rows.map(r => {\n      const st = status[r._id]\n      const stHtml = r.authType === 'oauth2'\n        ? (st ? `<span class=\"status ${st.connected ? 'connected' : 'disconnected'}\">${st.connected ? 'conectado' : 'desconectado'}</span>` : `<span class=\"status unknown\">...</span>`)\n        : ''\n      return `\n      <div class=\"row\" data-key=\"${r._id}\">\n        <div class=\"name\">${esc(r.name)}${stHtml}</div>\n        <div class=\"url\">${esc(r.endpointUrl)}</div>\n        <button class=\"badge ${r.active ? 'on':'off'}\" data-id=\"${r._id}\" data-active=\"${r.active?1:0}\">${r.active?'Ativo':'Inativo'}</button>\n        <button class=\"iconbtn edit\" data-id=\"${r._id}\">Editar</button>\n        <button class=\"iconbtn danger del\" data-id=\"${r._id}\">Excluir</button>\n      </div>\n    `}).join('') : `<div class=\"empty\">Nenhum servidor MCP registrado ainda.</div>`\n\n    const authType = draft ? (draft.authType || 'none') : 'none'\n    const authFieldsHtml = draft ? (\n      authType === 'apiKey' ? `\n        <div class=\"row2\">\n          <div class=\"field\"><label>Auth header name</label><input class=\"f-authname\" value=\"${escAttr(draft.authHeaderName)}\" placeholder=\"Authorization ou X-API-Key\"/></div>\n          <div class=\"field\"><label>Auth header value</label><input class=\"f-authvalue\" value=\"${escAttr(draft.authHeaderValue)}\" placeholder=\"Bearer ~~vault/key~~\"/></div>\n        </div>\n        <div class=\"hint\">Use um placeholder de KeyVault (ex: ~~minha-vault/minha-chave~~) em vez do valor cru para nao expor o segredo.</div>\n      ` : authType === 'oauth2' ? `\n        <div class=\"row2\">\n          <div class=\"field\"><label>Client ID</label><input class=\"f-oauth-clientid\" value=\"${escAttr(draft.oauthClientId)}\" placeholder=\"client id\"/></div>\n          <div class=\"field\"><label>Client Secret (KeyVault placeholder)</label><input class=\"f-oauth-clientsecret\" value=\"${escAttr(draft.oauthClientSecret)}\" placeholder=\"~~vault/key~~\"/></div>\n        </div>\n        <div class=\"row2\">\n          <div class=\"field\"><label>Authorize URL</label><input class=\"f-oauth-authurl\" value=\"${escAttr(draft.oauthAuthorizeUrl)}\" placeholder=\"https://provider.com/oauth/authorize\"/></div>\n          <div class=\"field\"><label>Token URL</label><input class=\"f-oauth-tokenurl\" value=\"${escAttr(draft.oauthTokenUrl)}\" placeholder=\"https://provider.com/oauth/token\"/></div>\n        </div>\n        <div class=\"field\"><label>Scopes</label><input class=\"f-oauth-scopes\" value=\"${escAttr(draft.oauthScopes)}\" placeholder=\"read write\"/></div>\n        <div class=\"field\">\n          <label>Redirect URI (registre este exato valor no provedor)</label>\n          <div class=\"callbackBox\">${esc(callbackUrl)}</div>\n        </div>\n      ` : `<div class=\"hint\">Nenhuma autenticacao necessaria para conectar a este servidor.</div>`\n    ) : ''\n\n    const formHtml = draft ? `\n      <div class=\"formCard\">\n        <h2>${draft._id ? 'Editar servidor MCP' : 'Novo servidor MCP'}</h2>\n        <div class=\"field\"><label>Nome</label><input class=\"f-name\" value=\"${escAttr(draft.name)}\" placeholder=\"Flight Search\"/></div>\n        <div class=\"field\"><label>Endpoint URL</label><input class=\"f-url\" value=\"${escAttr(draft.endpointUrl)}\" placeholder=\"https://exemplo.com/mcp\"/></div>\n        <div class=\"field\"><label>Descricao (para o planner)</label><input class=\"f-desc\" value=\"${escAttr(draft.description)}\" placeholder=\"Busca de voos em tempo real...\"/></div>\n        <div class=\"field\">\n          <label>Tipo de autenticacao</label>\n          <select class=\"f-authtype\">\n            <option value=\"none\" ${authType==='none'?'selected':''}>Nenhuma</option>\n            <option value=\"apiKey\" ${authType==='apiKey'?'selected':''}>API Key / Header estatico</option>\n            <option value=\"oauth2\" ${authType==='oauth2'?'selected':''}>OAuth 2.0</option>\n          </select>\n        </div>\n        ${authFieldsHtml}\n        <div class=\"actions\">\n          <button class=\"btn ghost discover\" ${d2.state.discovering?'disabled':''}>${d2.state.discovering?'Descobrindo...':'Descobrir tools'}</button>\n          ${(draft._id && authType==='oauth2') ? `<button class=\"btn oauth connect\" data-id=\"${draft._id}\">Conectar (OAuth)</button>` : ''}\n        </div>\n        ${d2.state.discoverError ? `<div class=\"err\">${esc(d2.state.discoverError)}</div>` : ''}\n        <div class=\"field\"><label>Catalogo de tools (editavel, vai para o prompt do planner)</label><textarea class=\"f-catalog\" rows=\"6\">${esc(draft.catalogText)}</textarea></div>\n        <div class=\"actions\">\n          <button class=\"btn primary save\" ${d2.state.saving?'disabled':''}>${d2.state.saving?'Salvando...':'Salvar'}</button>\n          <button class=\"btn ghost cancel\">Cancelar</button>\n        </div>\n      </div>\n    ` : `<div class=\"actions\"><button class=\"btn primary new\">+ Novo servidor MCP</button></div>`\n\n    return `<div class=\"wrap\">\n      <div class=\"topbar\"><button class=\"iconbtn logout\">Sair</button></div>\n      <div>\n        <h1>Servidores MCP registrados</h1>\n        <div class=\"sub\">O chat consulta apenas os servidores marcados como Ativo.</div>\n        <div class=\"list\">${listHtml}</div>\n      </div>\n      ${formHtml}\n    </div>`\n  },\n  mounted(d2){\n    const blankDraft = () => ({ _id: null, name:'', endpointUrl:'', description:'', catalogText:'', authType:'none', authHeaderName:'', authHeaderValue:'', oauthClientId:'', oauthClientSecret:'', oauthAuthorizeUrl:'', oauthTokenUrl:'', oauthScopes:'' })\n\n    const refreshStatuses = async () => {\n      const ds = d2.data('_ziKSflmzxQR07d7vxg66DataSet')\n      if (!ds) return\n      try { await ds.refresh() } catch (e) { /* ignore, records() below still tries */ }\n      const rows = ds.records() || []\n      const oauthRows = rows.filter(r => r.authType === 'oauth2')\n      const next = { ...(d2.state.status||{}) }\n      for (const r of oauthRows) {\n        try {\n          const res = await d2.rush('mcpConnectionStatus').invoke({ mcpId: r._id })\n          const out = (res && res.data) ? res.data : res\n          next[r._id] = out\n        } catch (e) {\n          next[r._id] = { connected: false, error: (e && e.message) ? e.message : String(e) }\n        }\n      }\n      d2.state.status = next\n    }\n\n    d2.on('.new','click', () => { d2.state.draft = blankDraft(); d2.state.discoverError = '' })\n    d2.on('.cancel','click', () => { d2.state.draft = null; d2.state.discoverError = '' })\n    d2.on('.logout','click', async () => { await d2.auth(d2.params.authStrategy).logout(); d2.router().goTo('/admin') })\n\n    d2.on('.edit','click', (e) => {\n      const id = e.target.dataset.id\n      const ds = d2.data('_ziKSflmzxQR07d7vxg66DataSet')\n      const r = (ds && ds.records() || []).find(x => x._id === id)\n      if (r) { d2.state.draft = { _id: r._id, name: r.name||'', endpointUrl: r.endpointUrl||'', description: r.description||'', catalogText: r.catalogText||'', authType: r.authType||'none', authHeaderName: r.authHeaderName||'', authHeaderValue: r.authHeaderValue||'', oauthClientId: r.oauthClientId||'', oauthClientSecret: r.oauthClientSecret||'', oauthAuthorizeUrl: r.oauthAuthorizeUrl||'', oauthTokenUrl: r.oauthTokenUrl||'', oauthScopes: r.oauthScopes||'' }; d2.state.discoverError = '' }\n    })\n\n    d2.on('.badge','click', async (e) => {\n      const id = e.target.dataset.id\n      const active = e.target.dataset.active === '1'\n      const ds = d2.data('_ziKSflmzxQR07d7vxg66DataSet')\n      await ds.update({ _id: id, active: !active })\n      await ds.refresh()\n    })\n\n    d2.on('.del','click', async (e) => {\n      const id = e.target.dataset.id\n      const ok = await d2.dialog.confirm('Remover este servidor MCP?')\n      if (!ok) return\n      const ds = d2.data('_ziKSflmzxQR07d7vxg66DataSet')\n      await ds.remove(id)\n      await ds.refresh()\n      if (d2.state.draft && d2.state.draft._id === id) d2.state.draft = null\n    })\n\n    d2.on('.f-name','input', (e) => { d2.state.draft = { ...d2.state.draft, name: e.target.value } })\n    d2.on('.f-url','input', (e) => { d2.state.draft = { ...d2.state.draft, endpointUrl: e.target.value } })\n    d2.on('.f-desc','input', (e) => { d2.state.draft = { ...d2.state.draft, description: e.target.value } })\n    d2.on('.f-authtype','input', (e) => { d2.state.draft = { ...d2.state.draft, authType: e.target.value } })\n    d2.on('.f-authname','input', (e) => { d2.state.draft = { ...d2.state.draft, authHeaderName: e.target.value } })\n    d2.on('.f-authvalue','input', (e) => { d2.state.draft = { ...d2.state.draft, authHeaderValue: e.target.value } })\n    d2.on('.f-oauth-clientid','input', (e) => { d2.state.draft = { ...d2.state.draft, oauthClientId: e.target.value } })\n    d2.on('.f-oauth-clientsecret','input', (e) => { d2.state.draft = { ...d2.state.draft, oauthClientSecret: e.target.value } })\n    d2.on('.f-oauth-authurl','input', (e) => { d2.state.draft = { ...d2.state.draft, oauthAuthorizeUrl: e.target.value } })\n    d2.on('.f-oauth-tokenurl','input', (e) => { d2.state.draft = { ...d2.state.draft, oauthTokenUrl: e.target.value } })\n    d2.on('.f-oauth-scopes','input', (e) => { d2.state.draft = { ...d2.state.draft, oauthScopes: e.target.value } })\n    d2.on('.f-catalog','input', (e) => { d2.state.draft = { ...d2.state.draft, catalogText: e.target.value } })\n\n    d2.on('.discover','click', async () => {\n      const draft = d2.state.draft || {}\n      const url = (draft.endpointUrl || '').trim()\n      if (!url) { d2.state.discoverError = 'Informe o Endpoint URL antes de descobrir.'; return }\n      d2.state.discovering = true\n      d2.state.discoverError = ''\n      try {\n        const res = await d2.rush('mcpDiscoverTools').invoke({\n          endpointUrl: url,\n          authHeaderName: draft.authType === 'apiKey' ? (draft.authHeaderName || '') : '',\n          authHeaderValue: draft.authType === 'apiKey' ? (draft.authHeaderValue || '') : '',\n        })\n        const out = (res && res.data) ? res.data : res\n        const raw = (out && out.raw) ? out.raw : JSON.stringify(out)\n        d2.state.draft = { ...d2.state.draft, catalogText: raw }\n      } catch (err) {\n        d2.state.discoverError = 'Falha ao descobrir tools: ' + (err && err.message ? err.message : String(err))\n      } finally {\n        d2.state.discovering = false\n      }\n    })\n\n    d2.on('.connect','click', async (e) => {\n      const draft = d2.state.draft\n      if (!draft || !draft.oauthAuthorizeUrl || !draft.oauthClientId) { d2.state.discoverError = 'Preencha Client ID e Authorize URL antes de conectar.'; return }\n      const b64url = (bytes) => btoa(String.fromCharCode(...bytes)).replace(/\\+/g,'-').replace(/\\//g,'_').replace(/=+$/,'')\n      const randomString = (len) => { const arr = new Uint8Array(len); crypto.getRandomValues(arr); return b64url(arr) }\n      const codeVerifier = randomString(64)\n      const state = randomString(24)\n      const enc = new TextEncoder().encode(codeVerifier)\n      const digest = await crypto.subtle.digest('SHA-256', enc)\n      const codeChallenge = b64url(new Uint8Array(digest))\n      const callbackUrl = window.location.origin + '/admin/oauth-callback'\n      sessionStorage.setItem('mcpOauthPending', JSON.stringify({ state, codeVerifier, mcpId: draft._id, redirectUri: callbackUrl }))\n      const qs = new URLSearchParams({\n        response_type: 'code',\n        client_id: draft.oauthClientId,\n        redirect_uri: callbackUrl,\n        scope: draft.oauthScopes || '',\n        state: state,\n        code_challenge: codeChallenge,\n        code_challenge_method: 'S256',\n      })\n      window.location.href = draft.oauthAuthorizeUrl + (draft.oauthAuthorizeUrl.indexOf('?') >= 0 ? '&' : '?') + qs.toString()\n    })\n\n    d2.on('.save','click', async () => {\n      const draft = d2.state.draft\n      if (!draft || !draft.name || !draft.endpointUrl) { d2.state.discoverError = 'Nome e Endpoint URL sao obrigatorios.'; return }\n      d2.state.saving = true\n      try {\n        const ds = d2.data('_ziKSflmzxQR07d7vxg66DataSet')\n        const payload = {\n          name: draft.name, endpointUrl: draft.endpointUrl, description: draft.description, catalogText: draft.catalogText,\n          authType: draft.authType || 'none',\n          authHeaderName: draft.authType === 'apiKey' ? (draft.authHeaderName || '') : '',\n          authHeaderValue: draft.authType === 'apiKey' ? (draft.authHeaderValue || '') : '',\n          oauthClientId: draft.authType === 'oauth2' ? (draft.oauthClientId || '') : '',\n          oauthClientSecret: draft.authType === 'oauth2' ? (draft.oauthClientSecret || '') : '',\n          oauthAuthorizeUrl: draft.authType === 'oauth2' ? (draft.oauthAuthorizeUrl || '') : '',\n          oauthTokenUrl: draft.authType === 'oauth2' ? (draft.oauthTokenUrl || '') : '',\n          oauthScopes: draft.authType === 'oauth2' ? (draft.oauthScopes || '') : '',\n        }\n        if (draft._id) {\n          await ds.update({ _id: draft._id, ...payload })\n        } else {\n          await ds.create({ ...payload, active: true, createdAt: Date.now() })\n        }\n        await ds.refresh()\n        d2.state.draft = null\n      } catch (err) {\n        d2.state.discoverError = 'Falha ao salvar: ' + (err && err.message ? err.message : String(err))\n      } finally {\n        d2.state.saving = false\n      }\n    })\n\n    refreshStatuses()\n  },\n}\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;') }\nfunction escAttr(s){ return esc(s).replace(/\"/g,'&quot;') }"}},"authStrategy":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"authStrategy"}}}}}}}}}},{"_id":"6a740d9cd5a555faccfdb47a","component":"data2-core-types@Component","system":"69f8a1f302514a1d6508bdbc","params":{"extends":"data2-core-primitives@Block","component":"mcpAdminLogin","package":"pliskin","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n    .wrap{display:flex;align-items:center;justify-content:center;height:100%;width:100%;background:#0d0d12;font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif}\n    .card{width:340px;background:#16161d;border:1px solid #26262f;border-radius:16px;padding:28px;display:flex;flex-direction:column;gap:12px}\n    h1{font-size:16px;color:#fff;margin:0 0 4px 0}\n    .sub{font-size:12px;color:#999;margin-bottom:6px}\n    label{font-size:11px;opacity:.65;text-transform:uppercase;letter-spacing:.04em;color:#ccc;margin-bottom:2px;display:block}\n    input{width:100%;box-sizing:border-box;padding:10px 12px;border-radius:8px;border:1px solid #33333f;background:#0d0d12;color:#fff;font-size:14px}\n    input:focus{outline:none;border-color:#3ed47e}\n    .field{display:flex;flex-direction:column;gap:4px}\n    .btn{padding:10px 16px;border-radius:8px;border:none;font-weight:600;font-size:14px;cursor:pointer;background:#3ed47e;color:#062b16;margin-top:6px}\n    .btn:disabled{opacity:.5;cursor:default}\n    .err{color:#e79a9a;font-size:12px}\n  `,\n  render(d2){\n    const busy = !!d2.state.busy\n    return `<div class=\"wrap\">\n      <div class=\"card\">\n        <h1>MCP Servers Admin</h1>\n        <div class=\"sub\">Faca login para gerenciar os servidores MCP registrados.</div>\n        <div class=\"field\"><label>Email</label><input class=\"f-email\" type=\"email\" placeholder=\"admin@exemplo.com\"/></div>\n        <div class=\"field\"><label>Senha</label><input class=\"f-pass\" type=\"password\" placeholder=\"********\"/></div>\n        ${d2.state.error ? `<div class=\"err\">${esc(d2.state.error)}</div>` : ''}\n        <button class=\"btn login\" ${busy?'disabled':''}>${busy?'Entrando...':'Entrar'}</button>\n      </div>\n    </div>`\n  },\n  mounted(d2){\n    const doLogin = async () => {\n      const email = (d2.$('.f-email')||{}).value || ''\n      const pass = (d2.$('.f-pass')||{}).value || ''\n      if (!email || !pass) { d2.state.error = 'Informe email e senha.'; return }\n      d2.state.busy = true\n      d2.state.error = ''\n      try {\n        await d2.auth(d2.params.authStrategy).login({ credentials: { email: email, password: pass } })\n        if (d2.auth(d2.params.authStrategy).isAuthed) {\n          d2.router().goTo('/admin')\n        } else {\n          d2.state.error = 'Credenciais invalidas.'\n        }\n      } catch (err) {\n        d2.state.error = 'Falha no login: ' + (err && err.message ? err.message : String(err))\n      } finally {\n        d2.state.busy = false\n      }\n    }\n    d2.on('.login','click', doLogin)\n    d2.on('.f-pass','keydown', (e) => { if (e.key === 'Enter') doLogin() })\n  },\n}\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;') }"}},"authStrategy":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"authStrategy"}}}}}}}}}},{"_id":"6a7412b99754f002640b84b1","component":"data2-core-types@Component","system":"69f8a1f302514a1d6508bdbc","params":{"extends":"data2-core-primitives@Block","component":"mcpOauthCallback","package":"pliskin","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n    .wrap{display:flex;align-items:center;justify-content:center;height:100%;width:100%;background:#0d0d12;font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif}\n    .card{width:380px;background:#16161d;border:1px solid #26262f;border-radius:16px;padding:28px;display:flex;flex-direction:column;gap:14px;text-align:center}\n    h1{font-size:16px;color:#fff;margin:0}\n    .msg{font-size:13px;line-height:1.5}\n    .msg.working{color:#ccc}\n    .msg.success{color:#6ee7a0}\n    .msg.error{color:#e79a9a}\n    .back{color:#3ed47e;font-size:13px;text-decoration:none;margin-top:6px}\n  `,\n  render(d2){\n    const status = d2.state.status || 'working'\n    const msg = d2.state.message || 'Processando retorno do provedor...'\n    return `<div class=\"wrap\"><div class=\"card\">\n      <h1>Conexao OAuth</h1>\n      <div class=\"msg ${status}\">${esc(msg)}</div>\n      <a class=\"back\" href=\"/admin\">Voltar para o admin</a>\n    </div></div>`\n  },\n  mounted(d2){\n    const run = async () => {\n      try {\n        const params = new URLSearchParams(window.location.search)\n        const code = params.get('code')\n        const returnedState = params.get('state')\n        const pendingRaw = sessionStorage.getItem('mcpOauthPending')\n        if (!pendingRaw) { d2.state.status='error'; d2.state.message='Nenhuma solicitacao OAuth pendente encontrada nesta sessao do navegador.'; return }\n        const pending = JSON.parse(pendingRaw)\n        if (!code) { d2.state.status='error'; d2.state.message='O provedor nao retornou um \"code\".'; return }\n        if (returnedState !== pending.state) { d2.state.status='error'; d2.state.message='State nao confere (possivel CSRF) - conexao abortada.'; return }\n        const res = await d2.rush('mcpOauthExchange').invoke({ mcpId: pending.mcpId, code: code, codeVerifier: pending.codeVerifier, redirectUri: pending.redirectUri })\n        const out = (res && res.data) ? res.data : res\n        sessionStorage.removeItem('mcpOauthPending')\n        if (out && out.connected) {\n          d2.state.status = 'success'\n          d2.state.message = 'Conectado com sucesso! Volte ao admin para ver o status.'\n        } else {\n          d2.state.status = 'error'\n          d2.state.message = 'Falha ao trocar o code por um token de acesso.'\n        }\n      } catch (err) {\n        d2.state.status = 'error'\n        d2.state.message = 'Erro: ' + (err && err.message ? err.message : String(err))\n      }\n    }\n    run()\n  },\n}\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;') }"}}}}}}}},{"_id":"6a7422c082f74266a2c881e6","component":"data2-core-types@Component","system":"69f8a1f302514a1d6508bdbc","params":{"extends":"data2-core-primitives@Block","component":"mockOauthAuthorize","package":"pliskin","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n    .wrap{display:flex;align-items:center;justify-content:center;height:100%;width:100%;background:#0d0d12;font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif}\n    .card{width:380px;background:#16161d;border:1px solid #26262f;border-radius:16px;padding:28px;display:flex;flex-direction:column;gap:12px;text-align:center}\n    h1{font-size:16px;color:#fff;margin:0}\n    .sub{font-size:12px;color:#999;line-height:1.5}\n    .clientBox{font-size:11px;font-family:ui-monospace,monospace;color:#8fe6ac;background:#0d0d12;border:1px dashed #33333f;border-radius:8px;padding:8px;word-break:break-all}\n    .btn{padding:11px 16px;border-radius:8px;border:none;font-weight:600;font-size:14px;cursor:pointer;background:#3ed47e;color:#062b16;margin-top:8px}\n    .btn:disabled{opacity:.5}\n    .err{color:#e79a9a;font-size:12px}\n  `,\n  render(d2){\n    const busy = !!d2.state.busy\n    const err = d2.state.error\n    return `<div class=\"wrap\"><div class=\"card\">\n      <h1>Mock IdP - Autorizar acesso</h1>\n      <div class=\"sub\">Este e um provedor OAuth FALSO, usado apenas para testar o fluxo de conexao. Nenhuma credencial real e verificada.</div>\n      <div class=\"clientBox\">client_id: ${esc(d2.state.clientId||'')}</div>\n      ${err ? `<div class=\"err\">${esc(err)}</div>` : ''}\n      <button class=\"btn login\" ${busy?'disabled':''}>${busy?'Conectando...':'Login como Test User'}</button>\n    </div></div>`\n  },\n  mounted(d2){\n    const params = new URLSearchParams(window.location.search)\n    d2.state.clientId = params.get('client_id') || ''\n    const waitForDataset = async (name, tries) => {\n      for (let i = 0; i < tries; i++) {\n        const ds = d2.data(name)\n        if (ds) return ds\n        await new Promise(r => setTimeout(r, 200))\n      }\n      return d2.data(name)\n    }\n    d2.on('.login','click', async () => {\n      d2.state.busy = true\n      d2.state.error = ''\n      try {\n        const redirectUri = params.get('redirect_uri')\n        const state = params.get('state')\n        const codeChallenge = params.get('code_challenge')\n        const clientId = params.get('client_id')\n        if (!redirectUri) { d2.state.error = 'redirect_uri ausente na URL.'; d2.state.busy = false; return }\n        const ds = await waitForDataset(d2.params.codesDataset || 'mock-oauth-codesDataSet', 15)\n        if (!ds) { d2.state.error = 'Nao foi possivel acessar a tabela de codigos (dataset indisponivel).'; d2.state.busy = false; return }\n        const code = 'mockcode_' + Math.random().toString(36).slice(2) + Date.now().toString(36)\n        await ds.create({ code, codeChallenge: codeChallenge || '', clientId: clientId || '', redirectUri, used: false, createdAt: Date.now() })\n        const sep = redirectUri.indexOf('?') >= 0 ? '&' : '?'\n        window.location.href = redirectUri + sep + 'code=' + encodeURIComponent(code) + '&state=' + encodeURIComponent(state || '')\n      } catch (err) {\n        d2.state.error = 'Falha: ' + (err && err.message ? err.message : String(err))\n        d2.state.busy = false\n      }\n    })\n  },\n}\nfunction esc(s){ return String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;') }"}},"codesDataset":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"codesDataset"}}}}}}}}}},{"_id":"6a753eb8f1ed6fd5538492df","component":"data2-core-types@Component","system":"69f8a1f302514a1d6508bdbc","params":{"extends":"data2-core-primitives@Block","component":"harnessMoodAvatar","package":"pliskin","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n    .wrap{display:flex;align-items:center;gap:12px;padding:8px 16px;height:100%;box-sizing:border-box}\n    @keyframes moodPop{0%{transform:scale(.78);opacity:.35}55%{transform:scale(1.08)}100%{transform:scale(1);opacity:1}}\n    .badge{width:44px;height:44px;border-radius:50%;background:#f3f2ef;display:flex;align-items:center;justify-content:center;overflow:hidden;flex:none;font-size:22px;transition:background .25s ease;animation:moodPop .32s ease}\n    .badge img{width:32px;height:32px;object-fit:contain}\n    .meta{display:flex;flex-direction:column;gap:2px;min-width:0}\n    .label{font:600 13px system-ui;color:#1a1a1a;text-transform:capitalize;transition:opacity .2s ease}\n    .sub{font:11px system-ui;color:#8a8a8a}\n  `,\n  render(d2) {\n    const ui = d2.store('ui')\n    const mood = ui.get('mood', 'calm')\n    const url = ui.get('moodIllustrationUrl', '')\n    const busy = ui.get('isBusy', false)\n    return `<div class=\"wrap\">\n      <div class=\"badge\">${url ? `<img src=\"${url}\" alt=\"${mood}\"/>` : '🙂'}</div>\n      <div class=\"meta\">\n        <div class=\"label\">${mood}</div>\n        <div class=\"sub\">${busy ? 'thinking…' : 'ready'}</div>\n      </div>\n    </div>`\n  },\n  mounted(d2) {\n    const el = d2.$('.badge')\n    if (el) el.dataset.mood = d2.store('ui').get('mood', 'calm')\n  },\n  updated(d2) {\n    const el = d2.$('.badge')\n    if (!el) return\n    const mood = d2.store('ui').get('mood', 'calm')\n    if (el.dataset.mood !== mood) {\n      el.dataset.mood = mood\n      // restart the CSS animation — swapping a `src`/text attribute on an\n      // existing node doesn't replay `animation` on its own, so force a reflow.\n      el.style.animation = 'none'\n      void el.offsetWidth\n      el.style.animation = ''\n    }\n  }\n}"}},"ui":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"ui"}}}}}}}}}},{"_id":"6a753ec1b8cbe55ea59612d0","component":"data2-core-types@Component","system":"69f8a1f302514a1d6508bdbc","params":{"extends":"data2-core-primitives@Block","component":"harnessMessageList","package":"pliskin","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"function escapeHtml(s) {\n  return String(s == null ? '' : s)\n    .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')\n}\nfunction escapeAttr(s) {\n  return escapeHtml(s).replace(/\"/g, '&quot;')\n}\nfunction actionIcon(type) {\n  var map = { recall_memory: '🧠', remember: '💾', take_note: '📝', web_search: '🔍', mcp_tool: '🔧', draw: '🎨', analyze_image: '👀', edit_image: '✏️', convene_meeting: '🗣️', spawn_subagent: '🤖' }\n  return map[type] || '⚡'\n}\nfunction actionLabel(a) {\n  var t = a.type\n  if (t === 'recall_memory') return 'recalling \"' + (a.memoryQuery || '') + '\"'\n  if (t === 'remember') return 'saving that to memory'\n  if (t === 'take_note') return 'noting \"' + (a.noteTitle || '') + '\"'\n  if (t === 'web_search') return 'searching \"' + (a.webQuery || '') + '\"'\n  if (t === 'mcp_tool') return 'using ' + (a.mcpName || 'a tool') + '.' + (a.toolName || '')\n  if (t === 'draw') return 'drawing an image'\n  if (t === 'analyze_image') return 'looking at the image'\n  if (t === 'edit_image') return 'revising the image'\n  if (t === 'convene_meeting') return 'thinking it through: \"' + (a.meetingTopic || '') + '\"'\n  if (t === 'spawn_subagent') return 'delegating a sub-task'\n  return t || 'working'\n}\nfunction renderTraceEntry(t, i) {\n  if (t.status === 'mood') {\n    return '<div class=\"trace trace-mood\" data-key=\"t' + i + '\">' +\n      (t.illustrationUrl ? '<img src=\"' + escapeAttr(t.illustrationUrl) + '\"/>' : '') +\n      '<div class=\"trace-body\"><span class=\"trace-mood-label\">feeling ' + escapeHtml(t.mood || '') + '</span>' +\n      (t.reasoning ? '<span class=\"trace-reasoning\">' + escapeHtml(t.reasoning) + '</span>' : '') +\n      '</div></div>'\n  }\n  if (t.status === 'acting') {\n    var actions = t.actions || []\n    var chips = actions.map(function (a) { return '<span class=\"action-chip\">' + actionIcon(a.type) + ' ' + escapeHtml(actionLabel(a)) + '</span>' }).join('')\n    return '<div class=\"trace trace-acting\" data-key=\"t' + i + '\"><div class=\"action-chips\">' + chips + '</div></div>'\n  }\n  if (t.status === 'action_result') {\n    var isErr = (t.preview || '').indexOf('[error]') === 0\n    return '<div class=\"trace ' + (isErr ? 'trace-error' : 'trace-result') + '\" data-key=\"t' + i + '\"><span>' + (isErr ? '⚠️ ' : '✅ ') + escapeHtml(t.preview || 'done') + '</span></div>'\n  }\n  if (t.status === 'planning') {\n    return '<div class=\"trace trace-planning\" data-key=\"t' + i + '\"><span class=\"dots\">thinking</span></div>'\n  }\n  if (t.status === 'answering') {\n    return '<div class=\"trace trace-answering\" data-key=\"t' + i + '\"><span>writing the answer…</span></div>'\n  }\n  if (t.status === 'form') {\n    return '<div class=\"trace trace-form\" data-key=\"t' + i + '\"><span>preparing a form…</span></div>'\n  }\n  if (t.status === 'run_js') {\n    return '<div class=\"trace trace-acting\" data-key=\"t' + i + '\"><div class=\"action-chips\"><span class=\"action-chip\">⚡ ' + escapeHtml(t.jsPurpose || 'preparing code') + '</span></div></div>'\n  }\n  return '<div class=\"trace\" data-key=\"t' + i + '\"><span>' + escapeHtml(t.status || '…') + '</span></div>'\n}\n\nfunction unescapeEntities(s) {\n  return String(s)\n    .replace(/&quot;/g, '\"').replace(/&#39;/g, \"'\")\n    .replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&')\n}\n\nfunction renderRichBlocks(html) {\n  return html.replace(/<pre><code class=\"language-(chart|card)\">([\\s\\S]*?)<\\/code><\\/pre>/g, (full, kind, body) => {\n    try {\n      const spec = JSON.parse(unescapeEntities(body))\n      return kind === 'chart' ? renderChartSvg(spec) : renderCardHtml(spec)\n    } catch (e) {\n      return '<div class=\"rc-err\">could not render ' + kind + ' block</div>'\n    }\n  })\n}\n\nfunction renderCitationMarkers(html) {\n  const parts = html.split(/(<pre[\\s\\S]*?<\\/pre>)/g)\n  for (let i = 0; i < parts.length; i += 2) {\n    parts[i] = parts[i].replace(/\\[(\\d{1,2})\\]/g, '<sup class=\"cite-chip\">$1</sup>')\n  }\n  return parts.join('')\n}\n\nfunction renderChartSvg(spec) {\n  const type = spec.type || 'bar'\n  const labels = spec.labels || (spec.nodes ? spec.nodes.map((n) => n.label || n.id) : [])\n  const values = spec.values || []\n  const colors = ['#2563eb', '#16a34a', '#f59e0b', '#dc2626', '#7c3aed', '#0891b2', '#db2777']\n  if (type === 'flow') {\n    const nodes = spec.nodes || []\n    const boxW = 200, boxH = 40, gapY = 34\n    const rows = nodes.map((n, i) => {\n      const y = i * (boxH + gapY)\n      const arrow = i < nodes.length - 1 ? `<line x1=\"${boxW / 2}\" y1=\"${y + boxH}\" x2=\"${boxW / 2}\" y2=\"${y + boxH + gapY}\" stroke=\"#999\" stroke-width=\"2\" marker-end=\"url(#arrow)\"/>` : ''\n      return `<rect x=\"0\" y=\"${y}\" width=\"${boxW}\" height=\"${boxH}\" rx=\"10\" fill=\"#eef2ff\" stroke=\"#3a4b8a\"/>` +\n        `<text x=\"${boxW / 2}\" y=\"${y + boxH / 2 + 4}\" text-anchor=\"middle\" font-size=\"12\" fill=\"#1a1a1a\">${escapeHtml(String(n.label || n.id).slice(0, 24))}</text>` + arrow\n    }).join('')\n    const totalH = nodes.length * (boxH + gapY) - gapY\n    return `<div class=\"chart-wrap\"><svg viewBox=\"0 0 ${boxW} ${Math.max(totalH, boxH)}\" width=\"220\" height=\"${Math.max(totalH, boxH) * (220 / boxW)}\"><defs><marker id=\"arrow\" markerWidth=\"8\" markerHeight=\"8\" refX=\"4\" refY=\"4\" orient=\"auto\"><path d=\"M0,0 L8,4 L0,8 Z\" fill=\"#999\"/></marker></defs>${rows}</svg></div>`\n  }\n  if (type === 'pie') {\n    const total = values.reduce((a, b) => a + b, 0) || 1\n    let angle = -Math.PI / 2\n    const cx = 90, cy = 90, r = 70\n    const slices = values.map((v, i) => {\n      const a0 = angle\n      angle += (v / total) * Math.PI * 2\n      const a1 = angle\n      const x0 = cx + r * Math.cos(a0), y0 = cy + r * Math.sin(a0)\n      const x1 = cx + r * Math.cos(a1), y1 = cy + r * Math.sin(a1)\n      const large = (a1 - a0) > Math.PI ? 1 : 0\n      return `<path d=\"M${cx},${cy} L${x0},${y0} A${r},${r} 0 ${large} 1 ${x1},${y1} Z\" fill=\"${colors[i % colors.length]}\"><title>${escapeHtml(String(labels[i] || ''))}: ${v}</title></path>`\n    }).join('')\n    const legend = labels.map((l, i) => `<span class=\"chart-legend-item\"><i style=\"background:${colors[i % colors.length]}\"></i>${escapeHtml(String(l))} (${values[i]})</span>`).join('')\n    return `<div class=\"chart-wrap\"><svg viewBox=\"0 0 180 180\" width=\"180\" height=\"180\">${slices}</svg><div class=\"chart-legend\">${legend}</div></div>`\n  }\n  const W = 320, H = 170, PAD = 26\n  const max = Math.max(1, ...values)\n  const barW = (W - PAD * 2) / Math.max(1, values.length)\n  const bars = type === 'line' ? '' : values.map((v, i) => {\n    const h = (v / max) * (H - PAD * 2)\n    return `<rect x=\"${PAD + i * barW + 2}\" y=\"${H - PAD - h}\" width=\"${barW - 4}\" height=\"${h}\" fill=\"#2563eb\" rx=\"3\"><title>${escapeHtml(String(labels[i] || ''))}: ${v}</title></rect>`\n  }).join('')\n  let linePath = ''\n  if (type === 'line') {\n    const pts = values.map((v, i) => [PAD + i * barW + barW / 2, H - PAD - (v / max) * (H - PAD * 2)])\n    linePath = `<polyline points=\"${pts.map((p) => p.join(',')).join(' ')}\" fill=\"none\" stroke=\"#2563eb\" stroke-width=\"2.5\"/>` +\n      pts.map((p) => `<circle cx=\"${p[0]}\" cy=\"${p[1]}\" r=\"3.5\" fill=\"#2563eb\"/>`).join('')\n  }\n  const labelsHtml = labels.map((l, i) => `<text x=\"${PAD + i * barW + barW / 2}\" y=\"${H - 8}\" font-size=\"9\" text-anchor=\"middle\" fill=\"#888\">${escapeHtml(String(l).slice(0, 8))}</text>`).join('')\n  return `<div class=\"chart-wrap\"><svg viewBox=\"0 0 ${W} ${H}\" width=\"100%\" height=\"150\"><line x1=\"${PAD}\" y1=\"${H - PAD}\" x2=\"${W - PAD}\" y2=\"${H - PAD}\" stroke=\"#ddd\"/>${bars}${linePath}${labelsHtml}</svg></div>`\n}\n\nfunction renderCardHtml(spec) {\n  const type = spec.type || 'generic'\n  if (type === 'news') {\n    return `<div class=\"rc-card rc-news\">\n      ${spec.image ? `<img class=\"rc-news-img\" src=\"${escapeAttr(spec.image)}\" loading=\"lazy\"/>` : ''}\n      <div class=\"rc-news-body\">\n        <div class=\"rc-news-source\">${escapeHtml(spec.source || '')}</div>\n        <div class=\"rc-news-title\">${escapeHtml(spec.title || '')}</div>\n        <div class=\"rc-news-snippet\">${escapeHtml(spec.snippet || '')}</div>\n        ${spec.url ? `<a class=\"rc-news-link\" href=\"${escapeAttr(spec.url)}\" target=\"_blank\" rel=\"noopener noreferrer\">Ler mais →</a>` : ''}\n      </div>\n    </div>`\n  }\n  if (type === 'menu') {\n    const items = (spec.items || []).map((it) => `<div class=\"rc-menu-item\"><span class=\"rc-menu-name\">${escapeHtml(it.name || '')}</span><span class=\"rc-menu-price\">${escapeHtml(it.price || '')}</span></div>`).join('')\n    return `<div class=\"rc-card rc-menu\">\n      <div class=\"rc-menu-title\">${escapeHtml(spec.name || 'Menu')}</div>\n      <div class=\"rc-menu-list\">${items}</div>\n    </div>`\n  }\n  const fields = (spec.fields || []).map((f) => `<div class=\"rc-generic-row\"><span class=\"rc-generic-k\">${escapeHtml(f.label || f.key || '')}</span><span class=\"rc-generic-v\">${escapeHtml(f.value != null ? String(f.value) : '')}</span></div>`).join('')\n  return `<div class=\"rc-card rc-generic\">\n    ${spec.title ? `<div class=\"rc-generic-title\">${escapeHtml(spec.title)}</div>` : ''}\n    <div class=\"rc-generic-list\">${fields}</div>\n  </div>`\n}\n\nfunction renderMarkdown(d2, raw) {\n  const markedMod = d2.lib('marked@11.1.1')\n  const purifyMod = d2.lib('dompurify@3.0.8')\n  if (!markedMod || !purifyMod) return null\n  const markedFn = markedMod.marked || markedMod.default || markedMod\n  const purify = purifyMod.default || purifyMod\n  let html\n  try {\n    html = markedFn.parse ? markedFn.parse(raw || '', { gfm: true, breaks: true }) : markedFn(raw || '', { gfm: true, breaks: true })\n  } catch (e) {\n    return null\n  }\n  try {\n    // Explicit allowlist additions — don't rely on DOMPurify's default profile\n    // for <img>: real inline image rendering (drawn images + any image URLs\n    // referenced in web-search-derived answers) needs src/alt/loading kept.\n    const sanitized = purify.sanitize(html, {\n      ADD_TAGS: ['img'],\n      ADD_ATTR: ['target', 'rel', 'src', 'alt', 'loading']\n    })\n    return renderCitationMarkers(renderRichBlocks(sanitized))\n  } catch (e) {\n    return null\n  }\n}\n\nfunction postProcessCodeCopy(d2) {\n  const root = d2.$('.list')\n  if (!root) return\n  root.querySelectorAll('.bubble pre').forEach((pre) => {\n    if (pre.dataset.copyWired) return\n    pre.dataset.copyWired = '1'\n    pre.style.position = 'relative'\n    const btn = document.createElement('button')\n    btn.className = 'code-copy-btn'\n    btn.type = 'button'\n    btn.textContent = 'Copy'\n    btn.addEventListener('click', () => {\n      const code = pre.querySelector('code')\n      const text = code ? code.textContent : pre.textContent\n      navigator.clipboard.writeText(text || '').then(() => {\n        btn.textContent = 'Copied!'\n        setTimeout(() => { btn.textContent = 'Copy' }, 1400)\n      }).catch(() => {})\n    })\n    pre.appendChild(btn)\n  })\n}\n\nfunction postProcessLinks(d2) {\n  const links = d2.$$('.assistant .bubble a')\n  links.forEach((a) => {\n    a.setAttribute('target', '_blank')\n    a.setAttribute('rel', 'noopener noreferrer')\n  })\n}\n\n// Inline images (drawn, or referenced in an answer) get a lazy-load +\n// shimmer-while-loading treatment: shimmer background until the browser\n// fires `load`, then a class swap removes it. Idempotent — skips images\n// already wired (data-imgwired) so re-renders don't double-bind.\nfunction postProcessImages(d2) {\n  const imgs = d2.$$('.bubble img')\n  imgs.forEach((img) => {\n    if (img.dataset.imgwired) return\n    img.dataset.imgwired = '1'\n    img.classList.add('chat-img')\n    if (!img.getAttribute('loading')) img.setAttribute('loading', 'lazy')\n    if (img.complete && img.naturalWidth > 0) {\n      img.classList.add('loaded')\n    } else {\n      img.addEventListener('load', () => img.classList.add('loaded'), { once: true })\n      img.addEventListener('error', () => img.classList.add('loaded'), { once: true })\n    }\n  })\n}\n\nconst ANNOT_MAX_DIM = 640\n\nfunction setupAnnotCanvas(d2) {\n  const canvas = d2.$('.annot-canvas')\n  const img = d2.$('.annot-img')\n  if (!canvas || !img) return\n  if (canvas.dataset.wired) return\n  canvas.dataset.wired = '1'\n  const sync = () => {\n    const nw = img.naturalWidth || img.clientWidth || ANNOT_MAX_DIM\n    const nh = img.naturalHeight || img.clientHeight || ANNOT_MAX_DIM\n    const scale = Math.min(1, ANNOT_MAX_DIM / Math.max(nw, nh))\n    canvas.width = Math.max(1, Math.round(nw * scale))\n    canvas.height = Math.max(1, Math.round(nh * scale))\n  }\n  if (img.complete && img.naturalWidth) sync()\n  else img.addEventListener('load', sync, { once: true })\n  const ctx = canvas.getContext('2d')\n  let drawing = false\n  const pos = (e) => {\n    const r = canvas.getBoundingClientRect()\n    const sx = canvas.width / r.width\n    const sy = canvas.height / r.height\n    return [(e.clientX - r.left) * sx, (e.clientY - r.top) * sy]\n  }\n  canvas.onpointerdown = (e) => {\n    drawing = true\n    const [x, y] = pos(e)\n    ctx.beginPath()\n    ctx.moveTo(x, y)\n  }\n  canvas.onpointermove = (e) => {\n    if (!drawing) return\n    const [x, y] = pos(e)\n    ctx.strokeStyle = '#ef4444'\n    ctx.lineWidth = 4\n    ctx.lineCap = 'round'\n    ctx.lineJoin = 'round'\n    ctx.lineTo(x, y)\n    ctx.stroke()\n  }\n  const stop = () => { drawing = false }\n  canvas.onpointerup = stop\n  canvas.onpointerleave = stop\n}\n\nfunction compositeAnnotation(d2) {\n  const canvas = d2.$('.annot-canvas')\n  const img = d2.$('.annot-img')\n  if (!canvas || !img || !canvas.width) return null\n  try {\n    const out = document.createElement('canvas')\n    out.width = canvas.width\n    out.height = canvas.height\n    const ctx = out.getContext('2d')\n    ctx.drawImage(img, 0, 0, out.width, out.height)\n    ctx.drawImage(canvas, 0, 0)\n    return out.toDataURL('image/jpeg', 0.82)\n  } catch (err) {\n    return null\n  }\n}\n\nfunction scrollToArtifact(d2, id) {\n  d2.store('ui').set('artifactsOpen', false)\n  setTimeout(() => {\n    const row = d2.$('[data-key=\"' + id + '\"]')\n    if (row) row.scrollIntoView({ behavior: 'smooth', block: 'center' })\n  }, 260)\n}\n\nconst revealCache = new Map()\n\nfunction isInsidePre(node, root) {\n  let p = node.parentElement\n  while (p && p !== root) {\n    if (p.tagName === 'PRE') return true\n    p = p.parentElement\n  }\n  return false\n}\n\nfunction wrapWordsForReveal(root, totalBudgetMs) {\n  const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null)\n  const candidates = []\n  let n\n  while ((n = walker.nextNode())) {\n    if (!isInsidePre(n, root) && /\\S/.test(n.nodeValue)) candidates.push(n)\n  }\n  if (candidates.length === 0) return\n  const perNodeTokens = candidates.map((node) => node.nodeValue.split(/(\\s+)/).filter((t) => t.length > 0))\n  let totalWords = 0\n  perNodeTokens.forEach((tokens) => tokens.forEach((t) => { if (/\\S/.test(t)) totalWords++ }))\n  if (totalWords === 0) return\n  const perWordDelay = Math.min(22, totalBudgetMs / totalWords)\n  let wordIndex = 0\n  candidates.forEach((node, i) => {\n    const tokens = perNodeTokens[i]\n    const frag = document.createDocumentFragment()\n    tokens.forEach((tok) => {\n      if (/\\S/.test(tok)) {\n        const span = document.createElement('span')\n        span.className = 'word'\n        span.textContent = tok\n        span.style.animationDelay = (wordIndex * perWordDelay).toFixed(1) + 'ms'\n        wordIndex++\n        frag.appendChild(span)\n      } else {\n        frag.appendChild(document.createTextNode(tok))\n      }\n    })\n    node.parentNode.replaceChild(frag, node)\n  })\n}\n\nfunction getAssistantBubbleHtml(d2, m, isTheFreshOne) {\n  const cached = revealCache.get(m._id)\n  if (cached) return cached\n  const html = renderMarkdown(d2, m.content)\n  if (html == null) return null\n  if (!isTheFreshOne) {\n    revealCache.set(m._id, html)\n    return html\n  }\n  const container = document.createElement('div')\n  container.innerHTML = html\n  wrapWordsForReveal(container, 820)\n  const decorated = container.innerHTML\n  revealCache.set(m._id, decorated)\n  return decorated\n}\n\nfunction renderFormField(f) {\n  const key = escapeAttr(f.key || '')\n  const label = escapeHtml(f.label || f.key || '')\n  const req = f.required ? '<span class=\"req\">*</span>' : ''\n  const placeholder = escapeAttr(f.placeholder || '')\n  let inputHtml = ''\n  if (f.type === 'select') {\n    const opts = (f.options || []).map((o) => `<option value=\"${escapeAttr(o)}\">${escapeHtml(o)}</option>`).join('')\n    inputHtml = `<select class=\"form-input\" data-key=\"${key}\"><option value=\"\">Select…</option>${opts}</select>`\n  } else if (f.type === 'textarea') {\n    inputHtml = `<textarea class=\"form-input\" data-key=\"${key}\" placeholder=\"${placeholder}\"></textarea>`\n  } else {\n    const type = (f.type === 'number' || f.type === 'date') ? f.type : 'text'\n    inputHtml = `<input class=\"form-input\" data-key=\"${key}\" type=\"${type}\" placeholder=\"${placeholder}\"/>`\n  }\n  return `<label class=\"form-field\">\n    <span class=\"form-label\">${label}${req}</span>\n    ${inputHtml}\n  </label>`\n}\n\nfunction renderFormRequest(m, isLive) {\n  const fields = m.formFields || []\n  if (!isLive) {\n    return `<div class=\"form-card readonly\" data-key=\"${m._id}\">\n      <div class=\"form-title\">${escapeHtml(m.formTitle || 'Form')}</div>\n      <div class=\"form-ro-note\">Answered earlier in this conversation</div>\n    </div>`\n  }\n  const inputsHtml = fields.map(renderFormField).join('')\n  return `<div class=\"form-card\" data-key=\"${m._id}\" data-form-id=\"${m._id}\">\n    <div class=\"form-title\">${escapeHtml(m.formTitle || 'Form')}</div>\n    <div class=\"form-body\">${inputsHtml}</div>\n    <div class=\"form-err\"></div>\n    <button class=\"form-submit\" type=\"button\">Submit</button>\n  </div>`\n}\n\nfunction renderRunJsCard(m, isLive) {\n  const code = (m.chunkData && m.chunkData.code) || ''\n  const already = m.chunkData && m.chunkData.ranResult !== undefined\n  return `<div class=\"js-card\" data-key=\"${m._id}\" data-js-id=\"${m._id}\">\n    <div class=\"js-title\">⚡ ${escapeHtml(m.content || 'Run code')}</div>\n    <pre class=\"js-code\"><code>${escapeHtml(code)}</code></pre>\n    ${already\n      ? `<div class=\"js-result\">= ${escapeHtml(String(m.chunkData.ranResult))}</div>`\n      : `<button class=\"js-run\" type=\"button\">▶ Executar no seu navegador</button><div class=\"js-err\"></div>`\n    }\n  </div>`\n}\n\nfunction renderFormSubmissionCard(m) {\n  const data = m.formData || {}\n  const keys = Object.keys(data)\n  const rows = keys.map((k) => `<div class=\"fs-row\"><span class=\"fs-k\">${escapeHtml(k)}</span><span class=\"fs-v\">${escapeHtml(String(data[k]))}</span></div>`).join('')\n  return `<div class=\"fs-card\" data-key=\"${m._id}\">\n    <div class=\"fs-title\">Submitted${m.formTitle ? ': ' + escapeHtml(m.formTitle) : ''}</div>\n    ${rows || `<div class=\"fs-row\"><span class=\"fs-v\">${escapeHtml(m.content)}</span></div>`}\n  </div>`\n}\n\nexport default {\n  css: `\n    .list{height:100%;overflow-y:auto;padding:16px;box-sizing:border-box;display:flex;flex-direction:column;gap:10px;font:14px system-ui;scroll-behavior:smooth}\n    @keyframes msgIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}\n    .row{display:flex;animation:msgIn .22s ease both}\n    .row.user{justify-content:flex-end}\n    .row.assistant{justify-content:flex-start}\n    .bubble{max-width:72%;padding:10px 14px;border-radius:14px;line-height:1.5}\n    .bubble.plain{white-space:pre-wrap}\n    .user .bubble{background:#2563eb;color:#fff;border-bottom-right-radius:4px}\n    .assistant .bubble{background:#f1f1ef;color:#1a1a1a;border-bottom-left-radius:4px}\n    .assistant .bubble p{margin:0 0 8px}\n    .assistant .bubble p:last-child{margin-bottom:0}\n    .assistant .bubble ul,.assistant .bubble ol{margin:0 0 8px;padding-left:22px}\n    .assistant .bubble li{margin:2px 0}\n    .assistant .bubble strong{font-weight:700}\n    .assistant .bubble a{color:#1d4ed8;text-decoration:underline}\n    .assistant .bubble code{background:#e7e6e2;border-radius:4px;padding:1px 5px;font:12.5px ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}\n    .assistant .bubble pre{background:#1c1c22;color:#e8e8e8;border-radius:10px;padding:10px 12px;overflow-x:auto;margin:0 0 8px;position:relative}\n    .code-copy-btn{position:absolute;top:6px;right:6px;border:none;background:rgba(255,255,255,.12);color:#ddd;border-radius:6px;padding:3px 9px;font:11px system-ui;cursor:pointer;opacity:0;transition:opacity .15s ease}\n    .assistant .bubble pre:hover .code-copy-btn{opacity:1}\n    .code-copy-btn:hover{background:rgba(255,255,255,.22)}\n    .assistant .bubble pre code{background:none;color:inherit;padding:0}\n    .assistant .bubble blockquote{margin:0 0 8px;padding-left:10px;border-left:3px solid #d8d8d3;color:#55554f}\n    .assistant .bubble table{border-collapse:collapse;margin:0 0 8px;font-size:13px}\n    .assistant .bubble th,.assistant .bubble td{border:1px solid #ddd;padding:4px 8px;text-align:left}\n    .bubble img.chat-img{max-width:100%;border-radius:12px;display:block;margin:4px 0 8px;background:linear-gradient(100deg,#eceae4 30%,#f6f5f1 50%,#eceae4 70%);background-size:200% 100%;animation:shimmer 1.2s ease-in-out infinite}\n    .bubble img.chat-img.loaded{animation:none;background:none}\n    @keyframes shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}\n    .chat-img{max-width:280px}\n    img.chat-img{border:1px solid rgba(0,0,0,.06)}\n    .preview img{max-width:none}\n    .user img.chat-img{max-width:220px}\n    @keyframes wordIn{from{opacity:0;filter:blur(6px);transform:translateY(8px)}to{opacity:1;filter:blur(0);transform:translateY(0)}}\n    .word{display:inline-block;animation:wordIn 520ms cubic-bezier(0.16,1,0.3,1) both}\n    @media (prefers-reduced-motion: reduce){\n      .word{animation:none !important;opacity:1 !important;filter:none !important;transform:none !important}\n    }\n    .trace{font-size:12px;color:#8a8a8a;background:#fafafa;border:1px dashed #ddd;border-radius:10px;padding:8px 12px;display:flex;gap:8px;align-items:center;animation:msgIn .22s ease both}\n    .trace img{width:18px;height:18px;border-radius:50%;flex:none}\n    .trace-mood{align-items:flex-start}\n    .trace-body{display:flex;flex-direction:column;gap:2px}\n    .trace-mood-label{font-weight:600;color:#555;text-transform:capitalize}\n    .trace-reasoning{color:#9a9a9a;font-style:italic}\n    .action-chips{display:flex;flex-wrap:wrap;gap:6px}\n    .action-chip{background:#eef2ff;color:#3a4b8a;border-radius:999px;padding:3px 10px;font:12px system-ui;white-space:nowrap}\n    .trace-result{color:#16a34a}\n    .trace-error{color:#dc2626}\n    @keyframes dotPulse{0%,80%,100%{opacity:.25}40%{opacity:1}}\n    .dots::after{content:'…';display:inline-block;animation:dotPulse 1.2s infinite}\n    .think-toggle{border:none;background:none;color:#9a9a9a;font:12px system-ui;cursor:pointer;padding:4px 0 0;text-align:left}\n    .think-toggle:hover{color:#666}\n    .think-body{display:none;color:#8a8a8a;font:12.5px system-ui;font-style:italic;background:#f7f7f5;border-radius:8px;padding:8px 10px;margin-top:4px;max-width:100%}\n    .think-body.open{display:block}\n    .think-evidence{white-space:pre-wrap;margin-top:6px;padding-top:6px;border-top:1px dashed #ddd;font-family:ui-monospace,monospace;font-size:11.5px;max-height:220px;overflow-y:auto}\n    .img-actions{display:flex;gap:6px;margin-top:6px}\n    .img-actions button{border:none;background:#f1f1ef;color:#555;border-radius:999px;padding:4px 10px;font:12px system-ui;cursor:pointer}\n    .img-actions button:hover{background:#e6e6e2}\n    .annot-overlay{position:fixed;inset:0;background:rgba(20,20,20,.72);z-index:1000;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;padding:24px;box-sizing:border-box}\n    .annot-frame{position:relative;max-width:min(90vw,640px);max-height:60vh;display:inline-block;line-height:0}\n    .annot-img{max-width:min(90vw,640px);max-height:60vh;display:block;border-radius:10px}\n    .annot-canvas{position:absolute;top:0;left:0;width:100%;height:100%;border-radius:10px;touch-action:none;cursor:crosshair}\n    .annot-controls{display:flex;flex-direction:column;gap:10px;width:min(90vw,640px)}\n    .annot-input{border:none;border-radius:10px;padding:12px 14px;font:14px system-ui;background:#fff}\n    .annot-buttons{display:flex;gap:8px;justify-content:flex-end}\n    .annot-buttons button{border:none;border-radius:9px;padding:9px 16px;font:600 13px system-ui;cursor:pointer}\n    .annot-clear{background:#3a3a3a;color:#eee;margin-right:auto}\n    .annot-cancel{background:#55554f;color:#eee}\n    .annot-send{background:#2563eb;color:#fff}\n    .artifacts-backdrop{position:fixed;inset:0;background:rgba(20,20,20,.35);z-index:300}\n    .artifacts-panel{position:fixed;top:0;right:0;height:100%;width:min(360px,90vw);background:#fff;z-index:301;box-shadow:-4px 0 28px rgba(0,0,0,.14);display:flex;flex-direction:column;animation:slideInRight .25s cubic-bezier(.16,1,.3,1)}\n    @keyframes slideInRight{from{transform:translateX(100%)}to{transform:translateX(0)}}\n    .artifacts-header{display:flex;align-items:center;justify-content:space-between;padding:16px;border-bottom:1px solid #eee;font:600 14px system-ui}\n    .artifacts-close{border:none;background:#f1f1ef;border-radius:50%;width:26px;height:26px;cursor:pointer;font-size:13px}\n    .artifacts-empty{padding:24px;color:#9a9a9a;font:13px system-ui;text-align:center}\n    .artifacts-section-title{padding:14px 16px 6px;font:600 11px system-ui;color:#9a9a9a;text-transform:uppercase;letter-spacing:.04em}\n    .artifacts-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px;padding:0 16px}\n    .artifact-thumb{border:1px solid #eee;border-radius:10px;overflow:hidden;padding:0;cursor:pointer;aspect-ratio:1;background:#f6f6f4}\n    .artifact-thumb img{width:100%;height:100%;object-fit:cover;display:block}\n    .artifact-code-item{display:block;width:calc(100% - 32px);margin:0 16px 8px;text-align:left;border:1px solid #eee;background:#0f1115;color:#c9d1d9;border-radius:9px;padding:9px 12px;font:12px system-ui;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n    .empty{color:#9a9a9a;font:13px system-ui;text-align:center;margin-top:40px}\n    .form-card{max-width:78%;background:#fff;border:1px solid #e6e6e2;border-radius:16px;padding:16px 18px;box-shadow:0 1px 3px rgba(0,0,0,.05)}\n    .form-title{font:600 15px system-ui;margin-bottom:12px;color:#1a1a1a}\n    .form-body{display:flex;flex-direction:column;gap:12px}\n    .form-field{display:flex;flex-direction:column;gap:5px}\n    .form-label{font:600 12px system-ui;color:#55554f;letter-spacing:.02em}\n    .req{color:#dc2626;margin-left:2px}\n    .form-input{border:1px solid #ddd;border-radius:9px;padding:8px 10px;font:14px system-ui;background:#fafaf8;transition:border-color .15s ease,background .15s ease;box-sizing:border-box}\n    .form-input:focus{outline:none;border-color:#2563eb;background:#fff}\n    textarea.form-input{min-height:60px;resize:vertical}\n    .form-err{color:#dc2626;font:12px system-ui;margin-top:8px;display:none}\n    .form-err.show{display:block}\n    .form-submit{margin-top:14px;align-self:flex-start;border:none;border-radius:9px;padding:9px 20px;background:#111;color:#fff;font:600 13px system-ui;cursor:pointer}\n    .form-submit:hover{background:#2563eb}\n    .form-submit:disabled{background:#c8c8c8;cursor:default}\n    .form-card.readonly{opacity:.65}\n    .form-ro-note{font:12px system-ui;color:#9a9a9a}\n    .fs-card{background:#eaf0ff;border-radius:14px;padding:10px 14px;max-width:72%;border-bottom-right-radius:4px}\n    .fs-title{font:600 11px system-ui;color:#1a3fae;text-transform:uppercase;letter-spacing:.04em;margin-bottom:6px}\n    .fs-row{display:flex;justify-content:space-between;gap:12px;font:13px system-ui;padding:2px 0}\n    .fs-k{color:#3a4b8a;text-transform:capitalize}\n    .fs-v{color:#1a1a1a;font-weight:600;text-align:right}\n    .js-card{max-width:82%;background:#0f1115;border-radius:14px;padding:14px 16px;color:#e8e8e8}\n    .js-title{font:600 13px system-ui;margin-bottom:8px;color:#f0f0f0}\n    .js-code{background:#1a1c22;border-radius:9px;padding:10px 12px;font:12.5px ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;overflow-x:auto;margin:0 0 10px;white-space:pre;color:#c9d1d9}\n    .js-run{border:none;border-radius:9px;padding:8px 16px;background:#2563eb;color:#fff;font:600 12.5px system-ui;cursor:pointer}\n    .js-run:hover{background:#3b76ef}\n    .js-run:disabled{background:#3a3a3a;cursor:default}\n    .js-result{font:600 13px ui-monospace,monospace;color:#4ade80;margin-top:4px}\n    .js-note{font:12px system-ui;color:#8a8a8a}\n    .js-err{color:#f87171;font:12px system-ui;margin-top:6px}\n    .chart-wrap{margin:6px 0 10px;display:flex;flex-direction:column;gap:8px;align-items:flex-start}\n    .chart-legend{display:flex;flex-wrap:wrap;gap:8px;font:12px system-ui;color:#555}\n    .chart-legend-item{display:flex;align-items:center;gap:5px}\n    .chart-legend-item i{width:9px;height:9px;border-radius:50%;display:inline-block}\n    .rc-err{color:#dc2626;font:12px system-ui;padding:6px 0}\n    .rc-card{border-radius:14px;overflow:hidden;margin:6px 0 10px;max-width:340px;border:1px solid #e6e6e2;background:#fff}\n    .rc-news-img{width:100%;height:140px;object-fit:cover;display:block;background:#eee}\n    .rc-news-body{padding:12px 14px}\n    .rc-news-source{font:600 11px system-ui;color:#8a8a8a;text-transform:uppercase;letter-spacing:.03em}\n    .rc-news-title{font:600 14.5px system-ui;color:#1a1a1a;margin:4px 0 6px}\n    .rc-news-snippet{font:13px system-ui;color:#555;line-height:1.4}\n    .rc-news-link{display:inline-block;margin-top:8px;font:600 12.5px system-ui;color:#2563eb;text-decoration:none}\n    .rc-menu{padding:14px 16px}\n    .rc-menu-title{font:700 15px system-ui;color:#1a1a1a;margin-bottom:10px;border-bottom:2px solid #111;padding-bottom:6px}\n    .rc-menu-item{display:flex;justify-content:space-between;gap:10px;font:13.5px system-ui;padding:5px 0;border-bottom:1px dashed #eee}\n    .rc-menu-name{color:#333}\n    .rc-menu-price{color:#111;font-weight:600;white-space:nowrap}\n    .rc-generic{padding:14px 16px}\n    .rc-generic-title{font:700 14px system-ui;margin-bottom:8px;color:#1a1a1a}\n    .rc-generic-row{display:flex;justify-content:space-between;gap:10px;font:13px system-ui;padding:4px 0}\n    .rc-generic-k{color:#8a8a8a}\n    .rc-generic-v{color:#1a1a1a;font-weight:600;text-align:right}\n    .mermaid-wrap svg{max-width:100%}\n    .cite-chip{display:inline-flex;align-items:center;justify-content:center;min-width:15px;height:15px;padding:0 3px;background:#eef2ff;color:#3a4b8a;border-radius:4px;font:600 10px system-ui;text-decoration:none;vertical-align:super;margin:0 1px;cursor:default}\n  `,\n  render(d2) {\n    const ui = d2.store('ui')\n    const sessionId = ui.get('activeSessionId', '')\n    const version = ui.get('messagesVersion', 0)\n    const liveTrace = ui.get('liveTrace', [])\n    const isBusy = ui.get('isBusy', false)\n    const key = sessionId + ':' + version\n\n    if (sessionId && d2.state.loadedKey !== key && !d2.state.loading) {\n      d2.state.loading = true\n      const isFreshSession = d2.state.loadedSessionId !== sessionId\n      d2.rush('harnessGetMessages').invoke({ sessionId: sessionId }).then((res) => {\n        const inner = (res && res.data) || {}\n        const msgs = inner.messages || []\n        if (isFreshSession) {\n          const nextKnown = {}\n          msgs.forEach((m) => { nextKnown[m._id] = true })\n          d2.state.knownIds = nextKnown\n        } else {\n          const known = d2.state.knownIds || {}\n          const fresh = msgs.filter((m) => !known[m._id])\n          const freshAssistant = fresh.filter((m) => m.role !== 'user').pop()\n          if (freshAssistant) {\n            d2.state.animatingMessageId = freshAssistant._id\n            d2.state.animatingUntil = Date.now() + 1500\n          }\n          const nextKnown = Object.assign({}, known)\n          msgs.forEach((m) => { nextKnown[m._id] = true })\n          d2.state.knownIds = nextKnown\n        }\n        d2.state.messages = msgs\n        d2.state.loadedKey = key\n        d2.state.loadedSessionId = sessionId\n        d2.state.loading = false\n        ui.set('pendingUserText', '')\n      }).catch((e) => {\n        d2.state.loading = false\n        d2.state.loadErr = String(e)\n      })\n    }\n\n    const messages = sessionId ? (d2.state.messages || []) : []\n    const pendingUserText = ui.get('pendingUserText', '')\n    const animatingId = d2.state.animatingMessageId\n    const lastId = messages.length ? messages[messages.length - 1]._id : null\n\n    const msgHtml = messages.map((m) => {\n      if (m.role === 'user') {\n        if (m.kind === 'form_submission') {\n          return `<div class=\"row user\" data-key=\"${m._id}\">${renderFormSubmissionCard(m)}</div>`\n        }\n        const imgHtml = m.imageUrl ? `<img class=\"chat-img\" src=\"${escapeAttr(m.imageUrl)}\" loading=\"lazy\" alt=\"attached image\"/>` : ''\n        const textHtml = m.content ? escapeHtml(m.content) : ''\n        return `<div class=\"row user\" data-key=\"${m._id}\"><div class=\"bubble plain\">${imgHtml}${textHtml}</div></div>`\n      }\n      if (m.kind === 'form_request') {\n        return `<div class=\"row assistant\" data-key=\"${m._id}\">${renderFormRequest(m, m._id === lastId && !isBusy)}</div>`\n      }\n      if (m.kind === 'run_js_request') {\n        return `<div class=\"row assistant\" data-key=\"${m._id}\">${renderRunJsCard(m, m._id === lastId && !isBusy)}</div>`\n      }\n      const isFresh = m._id === animatingId\n      const decorated = getAssistantBubbleHtml(d2, m, isFresh)\n      const plainClass = decorated != null ? '' : ' plain'\n      const body = decorated != null ? decorated : escapeHtml(m.content)\n      const openThinks = d2.state.openThinks || {}\n      const evidenceText = (m.chunkData && m.chunkData.evidence) ? String(m.chunkData.evidence).trim() : ''\n      const reasoningHtml = (m.reasoning || evidenceText) ? (\n        '<button class=\"think-toggle\" type=\"button\" data-key=\"' + m._id + '\">💭 ' + (openThinks[m._id] ? 'hide steps' : 'show steps') + '</button>' +\n        '<div class=\"think-body' + (openThinks[m._id] ? ' open' : '') + '\">' +\n          (m.reasoning ? escapeHtml(m.reasoning) : '') +\n          (evidenceText ? '<div class=\"think-evidence\">' + escapeHtml(evidenceText) + '</div>' : '') +\n        '</div>'\n      ) : ''\n      const imgActionsHtml = (m.kind === 'image' && m.imageUrl) ? (\n        '<div class=\"img-actions\"><button class=\"img-ask\" type=\"button\" data-img=\"' + escapeAttr(m.imageUrl) + '\">❓ Ask</button>' +\n        '<button class=\"img-annotate\" type=\"button\" data-img=\"' + escapeAttr(m.imageUrl) + '\">✏️ Annotate</button></div>'\n      ) : ''\n      return `<div class=\"row assistant\" data-key=\"${m._id}\"><div class=\"bubble${plainClass}\">${body}${imgActionsHtml}${reasoningHtml}</div></div>`\n    }).join('')\n\n    const pendingHtml = pendingUserText\n      ? `<div class=\"row user\" data-key=\"pending\"><div class=\"bubble plain\">${escapeHtml(pendingUserText)}</div></div>`\n      : ''\n\n    const traceHtml = isBusy ? liveTrace.map((t, i) => renderTraceEntry(t, i)).join('') : ''\n\n    const bodyOut = (messages.length === 0 && !isBusy && !pendingUserText)\n      ? `<div class=\"empty\">Say hi to start a new conversation.</div>`\n      : msgHtml + pendingHtml + traceHtml\n\n    const annotate = d2.state.annotate\n    const overlayHtml = annotate ? (\n      '<div class=\"annot-overlay\">' +\n        '<div class=\"annot-frame\"><img class=\"annot-img\" crossorigin=\"anonymous\" src=\"' + escapeAttr(annotate.imageUrl) + '\"/><canvas class=\"annot-canvas\"></canvas></div>' +\n        '<div class=\"annot-controls\">' +\n          '<input class=\"annot-input\" type=\"text\" placeholder=\"What should change? e.g. make the sky sunset orange\"/>' +\n          '<div class=\"annot-buttons\"><button class=\"annot-clear\" type=\"button\">Clear sketch</button><button class=\"annot-cancel\" type=\"button\">Cancel</button><button class=\"annot-send\" type=\"button\">Use this</button></div>' +\n        '</div>' +\n      '</div>'\n    ) : ''\n\n    const artifactsOpen = ui.get('artifactsOpen', false)\n    const artifactImages = messages.filter((m) => m.kind === 'image' && m.imageUrl)\n    const artifactCode = messages.filter((m) => m.kind === 'run_js_request')\n    const artifactsHtml = artifactsOpen ? (\n      '<div class=\"artifacts-backdrop\"></div>' +\n      '<div class=\"artifacts-panel\">' +\n        '<div class=\"artifacts-header\"><span>🖼️ Artefatos desta conversa</span><button class=\"artifacts-close\" type=\"button\">✕</button></div>' +\n        (artifactImages.length === 0 && artifactCode.length === 0\n          ? '<div class=\"artifacts-empty\">Nada gerado ainda nesta conversa.</div>'\n          : (\n            (artifactImages.length ? '<div class=\"artifacts-section-title\">Imagens</div><div class=\"artifacts-grid\">' +\n              artifactImages.map((m) => '<button class=\"artifact-thumb\" type=\"button\" data-artifact-id=\"' + m._id + '\"><img src=\"' + escapeAttr(m.imageUrl) + '\"/></button>').join('') +\n              '</div>' : '') +\n            (artifactCode.length ? '<div class=\"artifacts-section-title\">Código</div>' +\n              artifactCode.map((m) => '<button class=\"artifact-code-item\" type=\"button\" data-artifact-id=\"' + m._id + '\">⚡ ' + escapeHtml(m.content || '') + '</button>').join('')\n              : '')\n          )\n        ) +\n      '</div>'\n    ) : ''\n\n    return `<div class=\"list\">${bodyOut}</div>${overlayHtml}${artifactsHtml}`\n  },\n  mounted(d2) {\n    const el = d2.$('.list')\n    if (el) {\n      el.dataset.nearBottom = 'true'\n      el.scrollTop = el.scrollHeight\n      d2.on('.list', 'scroll', (e, elx) => {\n        const distance = elx.scrollHeight - elx.scrollTop - elx.clientHeight\n        elx.dataset.nearBottom = distance < 120 ? 'true' : 'false'\n      })\n    }\n    postProcessLinks(d2)\n    postProcessImages(d2)\n    postProcessCodeCopy(d2)\n    setupAnnotCanvas(d2)\n\n    d2.on('.think-toggle', 'click', (e, el) => {\n      const id = el.getAttribute('data-key')\n      const open = d2.state.openThinks || {}\n      d2.state.openThinks = Object.assign({}, open, { [id]: !open[id] })\n    })\n\n    d2.on('.img-ask', 'click', (e, el) => {\n      const url = el.getAttribute('data-img')\n      const ui = d2.store('ui')\n      ui.set('pendingReferenceImageUrl', url)\n      const ta = document.querySelector('textarea')\n      if (ta) ta.focus()\n    })\n\n    d2.on('.img-annotate', 'click', (e, el) => {\n      const url = el.getAttribute('data-img')\n      d2.state.annotate = { imageUrl: url }\n    })\n\n    d2.on('.annot-cancel', 'click', () => { d2.state.annotate = null })\n\n    d2.on('.annot-clear', 'click', () => {\n      const canvas = d2.$('.annot-canvas')\n      if (canvas) { const ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, canvas.width, canvas.height) }\n    })\n\n    d2.on('.artifacts-close', 'click', () => { d2.store('ui').set('artifactsOpen', false) })\n    d2.on('.artifacts-backdrop', 'click', () => { d2.store('ui').set('artifactsOpen', false) })\n    d2.on('.artifact-thumb', 'click', (e, el) => { scrollToArtifact(d2, el.getAttribute('data-artifact-id')) })\n    d2.on('.artifact-code-item', 'click', (e, el) => { scrollToArtifact(d2, el.getAttribute('data-artifact-id')) })\n\n    d2.on('.annot-send', 'click', () => {\n      const input = d2.$('.annot-input')\n      const text = input ? input.value.trim() : ''\n      const ann = d2.state.annotate\n      if (!ann) return\n      const ui = d2.store('ui')\n      const composited = compositeAnnotation(d2)\n      ui.set('pendingReferenceImageUrl', composited || ann.imageUrl)\n      ui.set('pendingIsAnnotated', !!composited)\n      if (text) ui.set('pendingDraftText', text)\n      d2.state.annotate = null\n    })\n\n    d2.on('.js-run', 'click', async (e, btn) => {\n      const card = btn.closest('.js-card')\n      if (!card) return\n      const jsId = card.getAttribute('data-js-id')\n      const msg = (d2.state.messages || []).find((m) => m._id === jsId)\n      if (!msg) return\n      const code = (msg.chunkData && msg.chunkData.code) || ''\n      btn.disabled = true\n      let result, errText\n      try {\n        const fn = new Function(code)\n        result = fn()\n      } catch (err) {\n        errText = String(err)\n      }\n      const errEl = card.querySelector('.js-err')\n      if (errText) {\n        if (errEl) errEl.textContent = errText\n        btn.disabled = false\n        return\n      }\n      const resultText = (typeof result === 'object') ? JSON.stringify(result) : String(result)\n      const ui = d2.store('ui')\n      const sessionId = ui.get('activeSessionId', '')\n      const readableMessage = `Executei o código. Resultado: ${resultText}`\n      ui.set('isBusy', true)\n      ui.set('liveTrace', [])\n      ui.set('pendingUserText', readableMessage)\n      try {\n        const res = await d2.rush('harnessAsk').stream({\n          sessionId: sessionId,\n          message: readableMessage,\n          imageUrl: '',\n          kind: 'run_js_result',\n          formData: { code: code, result: resultText }\n        }, (u) => {\n          const p = (u && u.payload) || {}\n          if (p.status === 'mood') {\n            if (p.mood) ui.set('mood', p.mood)\n            ui.set('moodIllustrationUrl', p.illustrationUrl || '')\n          }\n          const trace = ui.get('liveTrace', [])\n          ui.set('liveTrace', trace.concat([p]))\n        })\n        const inner = (res && res.data) || {}\n        const out = inner.data || inner\n        if (out && out.sessionId) ui.set('activeSessionId', out.sessionId)\n        ui.set('messagesVersion', (ui.get('messagesVersion', 0) || 0) + 1)\n      } catch (err) {\n        if (errEl) errEl.textContent = String(err)\n      } finally {\n        ui.set('isBusy', false)\n        ui.set('liveTrace', [])\n      }\n    })\n\n    d2.on('.form-submit', 'click', async (e, btn) => {\n      const card = btn.closest('.form-card')\n      if (!card) return\n      const formId = card.getAttribute('data-form-id')\n      const msg = (d2.state.messages || []).find((m) => m._id === formId)\n      if (!msg) return\n      const fields = msg.formFields || []\n      const inputs = card.querySelectorAll('.form-input')\n      const data = {}\n      inputs.forEach((el) => {\n        const k = el.getAttribute('data-key')\n        data[k] = el.value\n      })\n      const missing = fields.filter((f) => f.required && !(data[f.key] || '').toString().trim()).map((f) => f.label || f.key)\n      const errEl = card.querySelector('.form-err')\n      if (missing.length) {\n        if (errEl) {\n          errEl.textContent = 'Please fill in: ' + missing.join(', ')\n          errEl.classList.add('show')\n        }\n        return\n      }\n      if (errEl) errEl.classList.remove('show')\n      btn.disabled = true\n      const summary = fields.map((f) => `${f.label || f.key}: ${data[f.key] || '—'}`).join('; ')\n      const readableMessage = `Submitted \"${msg.formTitle || 'form'}\": ${summary}`\n      const ui = d2.store('ui')\n      const sessionId = ui.get('activeSessionId', '')\n      ui.set('isBusy', true)\n      ui.set('liveTrace', [])\n      ui.set('pendingUserText', readableMessage)\n      try {\n        const res = await d2.rush('harnessAsk').stream({\n          sessionId: sessionId,\n          message: readableMessage,\n          imageUrl: '',\n          kind: 'form_submission',\n          formData: data\n        }, (u) => {\n          const p = (u && u.payload) || {}\n          if (p.status === 'mood') {\n            if (p.mood) ui.set('mood', p.mood)\n            ui.set('moodIllustrationUrl', p.illustrationUrl || '')\n          }\n          const trace = ui.get('liveTrace', [])\n          ui.set('liveTrace', trace.concat([p]))\n        })\n        const inner = (res && res.data) || {}\n        const out = inner.data || inner\n        if (out && out.sessionId) ui.set('activeSessionId', out.sessionId)\n        ui.set('messagesVersion', (ui.get('messagesVersion', 0) || 0) + 1)\n      } catch (err) {\n        d2.state.formSubmitError = String(err)\n      } finally {\n        ui.set('isBusy', false)\n        ui.set('liveTrace', [])\n      }\n    })\n  },\n  updated(d2) {\n    postProcessLinks(d2)\n    postProcessImages(d2)\n    postProcessCodeCopy(d2)\n    setupAnnotCanvas(d2)\n    const el = d2.$('.list')\n    if (!el) return\n    const ui = d2.store('ui')\n    const pending = ui.get('pendingUserText', '')\n    const revealing = !!(d2.state.animatingUntil && Date.now() < d2.state.animatingUntil)\n    const shouldFollow = !!pending || revealing || el.dataset.nearBottom !== 'false'\n    if (shouldFollow) el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' })\n  }\n}"}},"ui":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"ui"}}}}}}}}}},{"_id":"6a753ec7f1ed6fd5538492f4","component":"data2-core-types@Component","system":"69f8a1f302514a1d6508bdbc","params":{"extends":"data2-core-primitives@Block","component":"harnessChatInput","package":"pliskin","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n    .bar{display:flex;flex-direction:column;gap:6px;padding:10px 16px;box-sizing:border-box;height:100%;justify-content:center}\n    .preview{display:flex;align-items:center;gap:8px}\n    .preview img{width:40px;height:40px;object-fit:cover;border-radius:8px;border:1px solid #ddd}\n    .preview .rm, .preview .rm-ref{border:none;background:#f1f1ef;color:#666;border-radius:999px;width:20px;height:20px;font-size:11px;cursor:pointer;line-height:1;flex:none;padding:0}\n    .preview .lbl{font:12px system-ui;color:#888}\n    .qr-chip{display:block;margin-top:6px;border:none;background:#eef2ff;color:#3a4b8a;border-radius:999px;padding:6px 12px;font:12px system-ui;cursor:pointer;text-align:left;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n    .qr-chip:hover{background:#dfe6ff}\n    .row{display:flex;gap:8px;align-items:flex-end}\n    textarea{flex:1;resize:none;border:1px solid #ddd;border-radius:10px;padding:10px 12px;font:14px system-ui;height:44px;max-height:120px;box-sizing:border-box}\n    button{border:none;border-radius:10px;padding:0 18px;height:44px;background:#2563eb;color:#fff;font:600 14px system-ui;cursor:pointer}\n    button:disabled{background:#c8c8c8;cursor:default}\n    .attach{background:#f1f1ef;color:#555;width:44px;padding:0;cursor:pointer;font-size:16px}\n    .attach:disabled{cursor:not-allowed;color:#bbb}\n    input[type=file]{display:none}\n  `,\n  render(d2) {\n    const ui = d2.store('ui')\n    const busy = ui.get('isBusy', false)\n    const text = d2.state.text || ''\n    const imgUrl = d2.state.attachedImageUrl || ''\n    const pendingRef = !imgUrl ? ui.get('pendingReferenceImageUrl', '') : ''\n    const uploading = !!d2.state.uploading\n    d2.lib('jsqr@1.4.0')\n    const qr = d2.state.qrDecoded\n    const qrChip = (qr && imgUrl) ? `<button class=\"qr-chip\" type=\"button\">🔍 QR encontrado: ${qr.slice(0, 60).replace(/\"/g, '&quot;')} — usar</button>` : ''\n    const previewBase = imgUrl\n      ? `<div class=\"preview\"><img src=\"${imgUrl.replace(/\"/g, '&quot;')}\"/><button class=\"rm\" type=\"button\">✕</button><span class=\"lbl\">image attached</span></div>`\n      : (pendingRef ? `<div class=\"preview\"><img src=\"${pendingRef.replace(/\"/g, '&quot;')}\"/><button class=\"rm-ref\" type=\"button\">✕</button><span class=\"lbl\">replying about this image</span></div>`\n      : (uploading ? `<div class=\"preview\"><span class=\"lbl\">uploading…</span></div>` : ''))\n    const preview = previewBase + qrChip\n    return `<div class=\"bar\">\n      ${preview}\n      <div class=\"row\">\n        <button class=\"attach\" title=\"Attach an image\" ${busy || uploading ? 'disabled' : ''}>📎</button>\n        <input type=\"file\" accept=\"image/*\"/>\n        <textarea placeholder=\"Message the harness…\" ${busy ? 'disabled' : ''}>${text}</textarea>\n        <button class=\"send\" ${busy || uploading ? 'disabled' : ''}>${busy ? '…' : 'Send'}</button>\n      </div>\n    </div>`\n  },\n  mounted(d2) {\n    d2.on('textarea', 'input', (e, el) => { d2.state.text = el.value })\n    d2.on('textarea', 'keydown', (e) => {\n      if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send() }\n    })\n    d2.on('textarea', 'paste', (e) => {\n      const items = (e.clipboardData && e.clipboardData.items) || []\n      for (let i = 0; i < items.length; i++) {\n        if (items[i].type && items[i].type.indexOf('image') === 0) {\n          const file = items[i].getAsFile()\n          if (file) { uploadImage(file); e.preventDefault(); break }\n        }\n      }\n    })\n    d2.on('.send', 'click', () => send())\n    d2.on('.attach', 'click', () => {\n      const el = d2.$('input[type=file]')\n      if (el) el.click()\n    })\n    d2.on('input[type=file]', 'change', (e, el) => {\n      const file = el.files && el.files[0]\n      if (file) uploadImage(file)\n      el.value = ''\n    })\n    d2.on('.rm', 'click', () => { d2.state.attachedImageUrl = ''; d2.state.qrDecoded = null })\n    d2.on('.qr-chip', 'click', () => {\n      if (d2.state.qrDecoded) d2.state.text = d2.state.qrDecoded\n    })\n    d2.on('.rm-ref', 'click', () => { d2.store('ui').set('pendingReferenceImageUrl', '') })\n\n    async function tryDecodeQr(file) {\n      try {\n        const jsQR = d2.lib('jsqr@1.4.0')\n        if (!jsQR) return null\n        const img = await new Promise((resolve, reject) => {\n          const im = new Image()\n          im.onload = () => resolve(im)\n          im.onerror = reject\n          im.src = URL.createObjectURL(file)\n        })\n        const canvas = document.createElement('canvas')\n        canvas.width = img.width\n        canvas.height = img.height\n        const ctx = canvas.getContext('2d')\n        ctx.drawImage(img, 0, 0)\n        const data = ctx.getImageData(0, 0, canvas.width, canvas.height)\n        const decodeFn = jsQR.default || jsQR\n        const code = decodeFn(data.data, data.width, data.height)\n        return code ? code.data : null\n      } catch (e) {\n        return null\n      }\n    }\n\n    async function uploadImage(file) {\n      d2.state.uploading = true\n      d2.state.uploadError = ''\n      d2.state.qrDecoded = null\n      tryDecodeQr(file).then((qr) => { if (qr) d2.state.qrDecoded = qr })\n      try {\n        const saved = await d2.drive('AgHbu4Y-aG6Qffwt77Kn8').uploadFromFiles([file])\n        const rec = saved && saved[0]\n        const url = rec && (rec.fileUrl || (rec.params && rec.params.fileUrl))\n        if (url) {\n          d2.state.attachedImageUrl = url\n        } else {\n          d2.state.uploadError = 'Upload did not return a file URL'\n        }\n      } catch (e) {\n        d2.state.uploadError = String(e)\n      } finally {\n        d2.state.uploading = false\n      }\n    }\n\n    async function send() {\n      const text = (d2.state.text || '').trim()\n      const ui = d2.store('ui')\n      const pendingRef = ui.get('pendingReferenceImageUrl', '')\n      const imageUrl = d2.state.attachedImageUrl || pendingRef || ''\n      if (!text && !imageUrl) return\n      if (ui.get('isBusy', false)) return\n      d2.state.text = ''\n      d2.state.attachedImageUrl = ''\n      ui.set('pendingReferenceImageUrl', '')\n      const ta = d2.$('textarea')\n      if (ta) ta.value = ''\n      const sessionId = ui.get('activeSessionId', '')\n      ui.set('isBusy', true)\n      ui.set('liveTrace', [])\n      ui.set('pendingUserText', text || '📷 Image attached')\n      try {\n        const res = await d2.rush('harnessAsk').stream({\n          sessionId: sessionId,\n          message: text,\n          imageUrl: imageUrl,\n          kind: (imageUrl ? 'image' : 'text'),\n          formData: {}\n        }, (u) => {\n          const p = (u && u.payload) || {}\n          if (p.status === 'mood') {\n            if (p.mood) ui.set('mood', p.mood)\n            ui.set('moodIllustrationUrl', p.illustrationUrl || '')\n          }\n          const trace = ui.get('liveTrace', [])\n          ui.set('liveTrace', trace.concat([p]))\n        })\n        const inner = (res && res.data) || {}\n        const out = inner.data || inner\n        if (out && out.sessionId) {\n          ui.set('activeSessionId', out.sessionId)\n        }\n        ui.set('messagesVersion', (ui.get('messagesVersion', 0) || 0) + 1)\n        d2.emit('onAsked', out)\n      } catch (e) {\n        d2.state.error = String(e)\n      } finally {\n        ui.set('isBusy', false)\n        ui.set('liveTrace', [])\n      }\n    }\n  },\n  updated(d2) {\n    syncTextarea(d2)\n    syncPendingDraft(d2)\n  }\n}\n\nfunction syncPendingDraft(d2) {\n  const ui = d2.store('ui')\n  const draft = ui.get('pendingDraftText', '')\n  if (draft) {\n    d2.state.text = draft\n    ui.set('pendingDraftText', '')\n  }\n}\n\nfunction syncTextarea(d2) {\n  const ta = d2.$('textarea')\n  const want = d2.state.text || ''\n  if (ta && ta.value !== want) ta.value = want\n}"}},"ui":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"ui"}}}}}}}}}},{"_id":"6a753ede9f1ece2343b4a635","component":"data2-core-types@Component","system":"69f8a1f302514a1d6508bdbc","params":{"extends":"data2-core-primitives@Block","component":"harnessChatShell","package":"pliskin","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"function setupViewportFix(d2) {\n  if (!window.visualViewport) return\n  const onResize = () => {\n    const root = d2.$('.shell')\n    if (root) root.style.height = window.visualViewport.height + 'px'\n  }\n  window.visualViewport.addEventListener('resize', onResize)\n  window.visualViewport.addEventListener('scroll', onResize)\n  onResize()\n}\n\nexport default {\n  css: `\n    .shell{display:grid;grid-template-columns:240px 1fr;grid-template-rows:1fr;height:100vh;height:100dvh;max-height:100vh;max-height:100dvh;box-sizing:border-box;font-family:system-ui;background:#fff;overflow:hidden;overscroll-behavior:none}\n    .sidebar{border-right:1px solid #eee;display:flex;flex-direction:column;height:100%;box-sizing:border-box}\n    .newchat{margin:12px;border:none;border-radius:10px;padding:10px;background:#111;color:#fff;font:600 13px system-ui;cursor:pointer}\n    .sessions{flex:1;overflow-y:auto;padding:0 8px}\n    .session{padding:10px 12px;border-radius:8px;font:13px system-ui;color:#333;cursor:pointer;margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n    .session:hover{background:#f4f4f4}\n    .session.active{background:#eaf0ff;color:#1a3fae;font-weight:600}\n    .main{display:grid;grid-template-rows:60px 1fr auto;height:100%;min-height:0;box-sizing:border-box;min-width:0}\n    .inputrow{max-height:45vh;overflow-y:auto}\n    .sidebar{min-height:0}\n    .topbar{border-bottom:1px solid #eee;display:flex;align-items:center;padding-top:env(safe-area-inset-top)}\n    .inputrow{padding-bottom:env(safe-area-inset-bottom)}\n    .msgs{overflow:hidden;min-height:0}\n    .inputrow{border-top:1px solid #eee}\n    .hamburger{display:none;border:none;background:none;font-size:19px;cursor:pointer;padding:0 6px 0 14px;color:#333;flex:none}\n    .artifacts-btn{margin-left:auto;margin-right:16px;border:none;background:#f1f1ef;color:#333;border-radius:999px;padding:7px 14px;font:600 12.5px system-ui;cursor:pointer;flex:none}\n    .artifacts-btn:hover{background:#e6e6e2}\n    .sidebar-backdrop{display:none}\n    @media (max-width: 760px) {\n      .shell{grid-template-columns:1fr}\n      .sidebar{position:fixed;top:0;left:0;height:100vh;height:100dvh;width:80vw;max-width:300px;background:#fff;z-index:200;transform:translateX(-100%);transition:transform .3s cubic-bezier(.16,1,.3,1);box-shadow:2px 0 28px rgba(0,0,0,.14)}\n      .sidebar.open{transform:translateX(0)}\n      .sidebar-backdrop{display:block;position:fixed;inset:0;background:rgba(20,20,20,.4);z-index:150;opacity:0;pointer-events:none;transition:opacity .25s ease}\n      .sidebar-backdrop.open{opacity:1;pointer-events:auto}\n      .hamburger{display:inline-block}\n    }\n  `,\n  render(d2) {\n    const ui = d2.store('ui')\n    const activeId = ui.get('activeSessionId', '')\n\n    if (!d2.state.sessionsLoaded || d2.state.sessionsNeedRefresh) {\n      d2.state.sessionsLoaded = true\n      d2.state.sessionsNeedRefresh = false\n      d2.rush('harnessListSessions').invoke({}).then((res) => {\n        const inner = (res && res.data) || {}\n        d2.state.sessions = inner.sessions || []\n      }).catch((e) => { d2.state.sessionsErr = String(e) })\n    }\n\n    const sessions = d2.state.sessions || []\n    const sessionRows = sessions.map((s) => `\n      <div class=\"session ${s._id === activeId ? 'active' : ''}\" data-id=\"${s._id}\" data-key=\"${s._id}\">\n        ${(s.title || s.lastMessage || s._id).toString().slice(0, 40) || 'Untitled session'}\n      </div>\n    `).join('')\n\n    const sidebarOpen = !!d2.state.sidebarOpen\n    return `<div class=\"shell\">\n      <div class=\"sidebar${sidebarOpen ? ' open' : ''}\">\n        <button class=\"newchat\">+ New chat</button>\n        <div class=\"sessions\">${sessionRows}</div>\n      </div>\n      <div class=\"sidebar-backdrop${sidebarOpen ? ' open' : ''}\"></div>\n      <div class=\"main\">\n        <div class=\"topbar\"><button class=\"hamburger\" type=\"button\" aria-label=\"Toggle sessions\">☰</button>${d2.render('pliskin@harnessMoodAvatar', { ui: d2.params.ui }, { key: 'mood' })}<button class=\"artifacts-btn\" type=\"button\">🖼️ Artefatos</button></div>\n        <div class=\"msgs\">${d2.render('pliskin@harnessMessageList', { ui: d2.params.ui }, { key: 'list' })}</div>\n        <div class=\"inputrow\">${d2.render('pliskin@harnessChatInput', { ui: d2.params.ui }, { key: 'input', onAsked: () => { d2.state.sessionsNeedRefresh = true } })}</div>\n      </div>\n    </div>`\n  },\n  mounted(d2) {\n    d2.on('.newchat', 'click', () => {\n      const ui = d2.store('ui')\n      ui.set('activeSessionId', '')\n      ui.set('messagesVersion', (ui.get('messagesVersion', 0) || 0) + 1)\n      ui.set('liveTrace', [])\n      ui.set('pendingUserText', '')\n      ui.set('mood', 'calm')\n      ui.set('moodIllustrationUrl', '')\n      d2.state.sidebarOpen = false\n    })\n    d2.on('.session', 'click', (e, el) => {\n      const id = el.getAttribute('data-id')\n      const ui = d2.store('ui')\n      ui.set('activeSessionId', id)\n      ui.set('messagesVersion', (ui.get('messagesVersion', 0) || 0) + 1)\n      ui.set('liveTrace', [])\n      ui.set('pendingUserText', '')\n      d2.state.sidebarOpen = false\n    })\n    d2.on('.hamburger', 'click', () => {\n      d2.state.sidebarOpen = !d2.state.sidebarOpen\n    })\n    d2.on('.sidebar-backdrop', 'click', () => {\n      d2.state.sidebarOpen = false\n    })\n    d2.on('.artifacts-btn', 'click', () => {\n      const ui = d2.store('ui')\n      ui.set('artifactsOpen', !ui.get('artifactsOpen', false))\n    })\n    setupViewportFix(d2)\n  }\n}"}},"ui":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"ui"}}}}}}}}}},{"_id":"6ab45c8ab7ce4747f39f0f87","component":"data2-core-types@Component","system":"69f8a1f302514a1d6508bdbc","params":{"extends":"data2-core-primitives@Block","component":"MCP_Infra_Diagram","package":"pliskin","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n    .wrap { font-family: ui-sans-serif, system-ui, sans-serif; padding: 32px; color: #e8eaf0; }\n    .mcp { text-align: center; margin-bottom: 28px; }\n    .mcp .box { display: inline-block; background: #3b2f6b; border: 2px solid #8a6ff0; border-radius: 10px; padding: 14px 28px; font-weight: 700; font-size: 18px; }\n    .arrow { text-align: center; color: #8a6ff0; font-size: 22px; margin: 4px 0; }\n    .row { display: flex; gap: 28px; justify-content: center; margin-bottom: 8px; }\n    .col { flex: 1; max-width: 460px; }\n    .group-label { text-align: center; font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em; color: #9aa0b4; margin-bottom: 6px; }\n    .svc { background: #1f2437; border: 1px solid #3a4160; border-radius: 8px; padding: 8px 12px; margin-bottom: 8px; font-size: 13px; }\n    .svc b { color: #8a6ff0; }\n    .tables { display: flex; gap: 20px; justify-content: center; margin-top: 20px; }\n    .table { background: #16321f; border: 2px solid #3fae5c; border-radius: 8px; padding: 12px 20px; font-size: 14px; font-weight: 600; }\n    .note { text-align: center; color: #9aa0b4; font-size: 12px; margin-top: 24px; }\n  `,\n  render(d2) {\n    return `\n      <div class=\"wrap\">\n        <div class=\"mcp\"><div class=\"box\">data2-mcp-builder (MCP)</div></div>\n        <div class=\"arrow\">↓</div>\n        <div class=\"row\">\n          <div class=\"col\">\n            <div class=\"group-label\">runtime · get_knowledge tool</div>\n            <div class=\"svc\"><b>articles-read</b> — get_knowledge(action:\"read\")</div>\n            <div class=\"svc\"><b>articles-search</b> — get_knowledge(action:\"search\")</div>\n          </div>\n          <div class=\"col\">\n            <div class=\"group-label\">dev-time · scripts/sync-knowledge-to-pliskin.ts</div>\n            <div class=\"svc\"><b>articles-upsert</b> — write one article</div>\n            <div class=\"svc\"><b>articles-list</b> — slug → id, for delete pre-flight</div>\n            <div class=\"svc\"><b>articles-delete-by-id</b> — remove stale rows (--full)</div>\n          </div>\n        </div>\n        <div class=\"arrow\">↓</div>\n        <div class=\"tables\">\n          <div class=\"table\">Articles (slug, title, content, tier, category, embedText)</div>\n          <div class=\"table\">KB Config (upsertToken — auth for the sync script)</div>\n        </div>\n        <div class=\"note\">Everything data2-mcp-builder depends on inside the pliskin system. Nothing else here (Lean Inception, Harness, MCP registry, demos) is part of this dependency graph.</div>\n      </div>\n    `\n  }\n}"}}}}}}}},{"_id":"6ab6a0877cc471b068c26208","component":"data2-core-types@Component","system":"69f8a1f302514a1d6508bdbc","params":{"extends":"data2-core-primitives@Block","component":"MCP_Usage_Dashboard","package":"pliskin","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n    .dash {\n      display:flex; flex-direction:column; gap:16px; height:100%; box-sizing:border-box;\n      padding:20px; background:#0b0b0d; color:#f2f2f5;\n      font-family:-apple-system,BlinkMacSystemFont,\"SF Pro Text\",\"Segoe UI\",system-ui,sans-serif;\n      overflow:auto;\n    }\n    .hdr { display:flex; align-items:baseline; justify-content:space-between; flex-wrap:wrap; gap:6px; }\n    .hdr h1 { font-size:15px; font-weight:600; margin:0; letter-spacing:-0.005em; }\n    .hdr .range { font-size:11px; color:#8a8a93; font-variant-numeric:tabular-nums; }\n    .warn { font-size:12px; color:#e8b04d; }\n    .chips { display:flex; flex-wrap:wrap; gap:6px; align-items:center; }\n    .chip { display:flex; align-items:center; gap:6px; background:#17171b; border:1px solid rgba(255,255,255,.12);\n      border-radius:999px; padding:4px 6px 4px 10px; font-size:11px; color:#d8d8dc; }\n    .chip b { color:#8fb8ff; font-weight:600; }\n    .chip .x { cursor:pointer; color:#8a8a93; width:16px; height:16px; border-radius:50%; display:flex;\n      align-items:center; justify-content:center; }\n    .chip .x:hover { background:rgba(255,255,255,.1); color:#fff; }\n    .clearall { font-size:11px; color:#8a8a93; cursor:pointer; text-decoration:underline; }\n    .clearall:hover { color:#fff; }\n    .kpis { display:grid; grid-template-columns:repeat(auto-fit,minmax(130px,1fr)); gap:10px; }\n    .kpi { background:#101013; border:1px solid rgba(255,255,255,.08); border-radius:10px; padding:12px 14px; }\n    .kpi .l { font-size:10.5px; text-transform:uppercase; letter-spacing:.04em; color:#8a8a93; pointer-events:none; }\n    .kpi .v { font-size:22px; font-weight:700; margin-top:4px; font-variant-numeric:tabular-nums; pointer-events:none; }\n    .kpi .v.err { color:#ff6a6a; }\n    .section { background:#101013; border:1px solid rgba(255,255,255,.08); border-radius:10px; padding:14px; position:relative; }\n    .section h2 { font-size:12px; font-weight:600; margin:0 0 10px; color:#c8c8cf; display:flex; align-items:center; justify-content:space-between; }\n    .section h2 .hint { font-size:10px; font-weight:400; color:#55555e; text-transform:none; letter-spacing:0; }\n    .row { display:flex; align-items:center; gap:8px; margin-bottom:5px; font-size:11.5px; cursor:pointer;\n      padding:3px 4px; border-radius:6px; }\n    .row:hover { background:rgba(255,255,255,.04); }\n    .row.active { background:rgba(91,134,255,.14); }\n    .row:last-child { margin-bottom:0; }\n    .row .name { width:180px; flex-shrink:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:#d8d8dc; pointer-events:none; }\n    .row.active .name { color:#8fb8ff; font-weight:600; }\n    .row .bar-wrap { flex:1; background:rgba(255,255,255,.06); border-radius:4px; height:14px; overflow:hidden; position:relative; pointer-events:none; }\n    .row .bar { display:block; position:relative; height:100%; background:linear-gradient(90deg,#5b86ff,#4ddfe6); border-radius:4px; min-width:2px; pointer-events:none; }\n    .row .bar .err-part { display:block; position:absolute; top:0; right:0; height:100%; background:#ff5a5a; pointer-events:none; }\n    .row .num { width:60px; text-align:right; font-variant-numeric:tabular-nums; color:#8a8a93; flex-shrink:0; pointer-events:none; }\n    .empty { color:#55555e; font-size:12px; padding:30px; text-align:center; }\n    .grid2 { display:grid; grid-template-columns:1fr 1fr; gap:14px; }\n    @media (max-width:700px){ .grid2{grid-template-columns:1fr;} }\n    table.events { width:100%; border-collapse:collapse; font-size:11px; }\n    table.events th { text-align:left; font-size:10px; text-transform:uppercase; letter-spacing:.04em; color:#8a8a93;\n      padding:6px 8px; border-bottom:1px solid rgba(255,255,255,.08); position:sticky; top:0; background:#101013; }\n    table.events td { padding:5px 8px; border-bottom:1px solid rgba(255,255,255,.04); color:#d8d8dc;\n      white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:220px; }\n    table.events tr:hover td { background:rgba(255,255,255,.03); }\n    table.events td.ok-false { color:#ff8080; }\n    .events-wrap { max-height:420px; overflow:auto; }\n    .clickable { cursor:pointer; }\n    .clickable:hover { text-decoration:underline; }\n    .expand-toggle { font-size:11px; color:#8fb8ff; cursor:pointer; padding:6px 4px 0; text-align:center; }\n    .expand-toggle:hover { text-decoration:underline; }\n    .hourly svg { width:100%; height:120px; display:block; }\n    .hourly .bar { fill:#5b86ff; }\n    .hourly .bar-err { fill:#ff5a5a; }\n    .hourly .bar:hover, .hourly .bar-err:hover { fill:#8fb8ff; }\n    .hourly-axis { position:relative; height:16px; margin-top:2px; }\n    .hourly-axis span { position:absolute; top:0; transform:translateX(-50%); font-size:9.5px; color:#55555e; white-space:nowrap; }\n    .hourly-axis span.day { color:#8a8a93; font-weight:600; }\n    .loading-veil { position:absolute; inset:0; background:rgba(11,11,13,.55); display:flex; align-items:center;\n      justify-content:center; font-size:11px; color:#8a8a93; border-radius:10px; }\n  `,\n  render(d2) {\n    const ds = d2.data()\n    if (!ds) return `<div class=\"dash\"><p class=\"empty\">Dataset not bound.</p></div>`\n\n    const esc = (v) => String(v == null ? '' : v).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')\n    const stats = d2.state.stats\n    const filter = d2.state.filter || {}\n\n    if (!stats) return `<div class=\"dash\"><p class=\"empty\">Loading MCP usage — running aggregations…</p></div>`\n    if (d2.state.fetchError) return `<div class=\"dash\"><p class=\"empty\" style=\"color:#ff8080\">Aggregation error: ${esc(d2.state.fetchError)}</p></div>`\n    if (!stats.total) return `<div class=\"dash\"><p class=\"empty\">No calls match the current filters.</p></div>`\n\n    const errRate = stats.total ? (stats.errors / stats.total) * 100 : 0\n\n    const DEFAULT_ROWS = 10\n    const expanded = d2.state.expanded || {}\n\n    const barList = (items, max, filterKey) => {\n      const isExpanded = !!expanded[filterKey]\n      const shown = isExpanded ? items : items.slice(0, DEFAULT_ROWS)\n      const rowsHtml = shown\n        .map((it) => {\n          const pct = max ? (it.calls / max) * 100 : 0\n          const errPct = it.calls ? (it.errors / it.calls) * 100 : 0\n          const isActive = filter[filterKey] === it.key\n          return `<div class=\"row ${isActive ? 'active' : ''}\" data-filter-type=\"${filterKey}\" data-filter-value=\"${esc(it.key)}\">\n            <span class=\"name\" title=\"${esc(it.key)}\">${esc(it.key)}</span>\n            <span class=\"bar-wrap\"><span class=\"bar\" style=\"width:${pct}%\"><span class=\"err-part\" style=\"width:${errPct}%\"></span></span></span>\n            <span class=\"num\">${d2.fmt.compact(it.calls)}</span>\n          </div>`\n        })\n        .join('')\n      const toggleHtml =\n        items.length > DEFAULT_ROWS\n          ? `<div class=\"expand-toggle\" data-expand-toggle=\"${filterKey}\">${isExpanded ? 'Show less' : `Show all ${items.length}`}</div>`\n          : ''\n      return rowsHtml + toggleHtml\n    }\n\n    const activeChips = []\n    if (filter.toolName) activeChips.push({ type: 'toolName', label: 'tool', value: filter.toolName })\n    if (filter.email) activeChips.push({ type: 'email', label: 'user', value: filter.email })\n    if (filter.systemId) activeChips.push({ type: 'systemId', label: 'system', value: filter.systemId })\n    if (filter.onlyErrors) activeChips.push({ type: 'onlyErrors', label: 'filter', value: 'errors only' })\n\n    const chipsHtml = activeChips.length\n      ? `<div class=\"chips\">\n          ${activeChips.map((c) => `<span class=\"chip\"><b>${esc(c.label)}</b>${esc(c.value)}<span class=\"x\" data-clear=\"${c.type}\">✕</span></span>`).join('')}\n          <span class=\"clearall\" data-clear=\"all\">clear all</span>\n        </div>`\n      : ''\n\n    const eventsHtml = (stats.events || []).length\n      ? stats.events\n          .map(\n            (r) => `<tr data-key=\"${esc(r._id)}\">\n              <td>${esc(r.timestamp ? d2.fmt.relative(new Date(r.timestamp)) : '—')}</td>\n              <td class=\"clickable\" data-filter-type=\"toolName\" data-filter-value=\"${esc(r.toolName)}\">${esc(r.toolName)}</td>\n              <td class=\"clickable\" data-filter-type=\"email\" data-filter-value=\"${esc(r.email)}\">${esc(r.email || '—')}</td>\n              <td class=\"clickable\" data-filter-type=\"systemId\" data-filter-value=\"${esc(r.systemId || '(none)')}\">${esc(r.systemId || '(none)')}</td>\n              <td class=\"${r.ok === false ? 'ok-false' : ''}\">${r.ok === false ? 'error' : 'ok'}</td>\n            </tr>`,\n          )\n          .join('')\n      : `<tr><td colspan=\"5\" style=\"text-align:center;color:#55555e;padding:20px\">No calls match the current filters.</td></tr>`\n\n    const hourly = stats.hourly || []\n    const hourlyChart = () => {\n      if (!hourly.length) return `<p class=\"empty\">No timestamped calls in the current filter.</p>`\n      const W = 100, H = 40, n = hourly.length, gap = n > 40 ? 0.15 : 0.4\n      const bw = (W - gap * (n - 1)) / n\n      const max = Math.max(1, ...hourly.map((h) => h.calls))\n      const labelEvery = Math.max(1, Math.ceil(n / 12))\n      const bars = hourly\n        .map((h, i) => {\n          const x = i * (bw + gap)\n          const hTotal = (h.calls / max) * H\n          const hErr = (h.errors / max) * H\n          const yTotal = H - hTotal\n          return `<rect class=\"bar\" x=\"${x}\" y=\"${yTotal}\" width=\"${bw}\" height=\"${hTotal}\" rx=\"0.3\">\n                    <title>${esc(h.hour)}:00 — ${h.calls} call${h.calls === 1 ? '' : 's'}${h.errors ? `, ${h.errors} error${h.errors === 1 ? '' : 's'}` : ''}</title>\n                  </rect>\n                  ${hErr ? `<rect class=\"bar-err\" x=\"${x}\" y=\"${H - hErr}\" width=\"${bw}\" height=\"${hErr}\" rx=\"0.3\"></rect>` : ''}`\n        })\n        .join('')\n      const labels = hourly\n        .map((h, i) => {\n          const isDayStart = h.hour.endsWith('T00')\n          if (!(i % labelEvery === 0 || isDayStart)) return ''\n          const x = i * (bw + gap)\n          const leftPct = ((x + bw / 2) / W) * 100\n          const text = isDayStart ? h.hour.slice(5, 10) : `${h.hour.slice(11, 13)}h`\n          return `<span class=\"${isDayStart ? 'day' : ''}\" style=\"left:${leftPct}%\">${esc(text)}</span>`\n        })\n        .join('')\n      return `<svg viewBox=\"0 0 ${W} ${H}\" preserveAspectRatio=\"none\">${bars}</svg><div class=\"hourly-axis\">${labels}</div>`\n    }\n\n    const veil = d2.state.loading ? `<div class=\"loading-veil\">updating…</div>` : ''\n\n    return `<div class=\"dash\">\n      <div class=\"hdr\">\n        <h1>MCP Usage</h1>\n        <span class=\"range\">real-time aggregation — full dataset, not a sample</span>\n      </div>\n      ${chipsHtml}\n      <div class=\"kpis\">\n        <div class=\"kpi\"><div class=\"l\">Calls</div><div class=\"v\">${d2.fmt.compact(stats.total)}</div></div>\n        <div class=\"kpi clickable\" data-clear-toggle-errors=\"1\"><div class=\"l\">Errors</div><div class=\"v err\">${d2.fmt.compact(stats.errors)}</div></div>\n        <div class=\"kpi\"><div class=\"l\">Error rate</div><div class=\"v\">${errRate.toFixed(1)}%</div></div>\n        <div class=\"kpi\"><div class=\"l\">Users</div><div class=\"v\">${stats.users}</div></div>\n        <div class=\"kpi\"><div class=\"l\">Systems</div><div class=\"v\">${stats.systems}</div></div>\n      </div>\n      <div class=\"section\">\n        <h2>Calls per hour <span class=\"hint\">hover a bar for the exact count · red = errors</span></h2>\n        <div class=\"hourly\">${hourlyChart()}</div>\n        ${veil}\n      </div>\n      <div class=\"grid2\">\n        <div class=\"section\">\n          <h2>Top tools <span class=\"hint\">click to filter</span></h2>\n          ${barList(stats.byTool, stats.byTool[0]?.calls || 1, 'toolName')}\n          ${veil}\n        </div>\n        <div class=\"section\">\n          <h2>Top users <span class=\"hint\">click to filter</span></h2>\n          ${barList(stats.byUser, stats.byUser[0]?.calls || 1, 'email')}\n          ${veil}\n        </div>\n      </div>\n      <div class=\"section\">\n        <h2>Top systems (by id) <span class=\"hint\">click to filter</span></h2>\n        ${barList(stats.bySystem, stats.bySystem[0]?.calls || 1, 'systemId')}\n        ${veil}\n      </div>\n      <div class=\"section\">\n        <h2>Calls <span class=\"hint\">newest ${(stats.events || []).length}, click tool/user/system to filter</span></h2>\n        <div class=\"events-wrap\">\n          <table class=\"events\">\n            <thead><tr><th>When</th><th>Tool</th><th>User</th><th>System</th><th>Status</th></tr></thead>\n            <tbody>${eventsHtml}</tbody>\n          </table>\n        </div>\n        ${veil}\n      </div>\n    </div>`\n  },\n  mounted(d2) {\n    const buildMatch = (filter) => {\n      const match = {}\n      if (filter.toolName) match.toolName = filter.toolName\n      if (filter.email) match.email = filter.email\n      if (filter.systemId) match.systemId = filter.systemId === '(none)' ? null : filter.systemId\n      if (filter.onlyErrors) match.ok = false\n      return match\n    }\n\n    const refetch = async () => {\n      const ds = d2.data()\n      if (!ds) return\n      d2.state.loading = true\n      const filter = d2.state.filter || {}\n      const match = buildMatch(filter)\n      const pre = Object.keys(match).length ? [{ $match: match }] : []\n      const errCond = { $sum: { $cond: [{ $eq: ['$ok', false] }, 1, 0] } }\n\n      const arr = (r) => (Array.isArray(r) ? r : r?.result || r?.records || r?.data || [])\n\n      try {\n        const [totalsResRaw, toolsResRaw, usersResRaw, systemsResRaw, hourlyResRaw, eventsResRaw] = await Promise.all([\n          ds.aggregate([...pre, { $group: { _id: null, total: { $sum: 1 }, errors: errCond, users: { $addToSet: '$email' }, systems: { $addToSet: '$systemId' } } }]),\n          ds.aggregate([...pre, { $group: { _id: '$toolName', calls: { $sum: 1 }, errors: errCond } }, { $sort: { calls: -1 } }, { $limit: 200 }]),\n          ds.aggregate([...pre, { $group: { _id: '$email', calls: { $sum: 1 }, errors: errCond } }, { $sort: { calls: -1 } }, { $limit: 200 }]),\n          ds.aggregate([...pre, { $group: { _id: '$systemId', calls: { $sum: 1 }, errors: errCond } }, { $sort: { calls: -1 } }, { $limit: 200 }]),\n          ds.aggregate([...pre, { $group: { _id: { $substrBytes: ['$timestamp', 0, 13] }, calls: { $sum: 1 }, errors: errCond } }, { $sort: { _id: 1 } }]),\n          ds.aggregate([...pre, { $sort: { timestamp: -1 } }, { $limit: 300 }]),\n        ])\n\n        const totalsRes = arr(totalsResRaw)\n        const toolsRes = arr(toolsResRaw)\n        const usersRes = arr(usersResRaw)\n        const systemsRes = arr(systemsResRaw)\n        const hourlyRes = arr(hourlyResRaw)\n        const eventsRes = arr(eventsResRaw)\n\n        const t = totalsRes?.[0] || { total: 0, errors: 0, users: [], systems: [] }\n        d2.state.stats = {\n          total: t.total || 0,\n          errors: t.errors || 0,\n          users: (t.users || []).filter(Boolean).length,\n          systems: (t.systems || []).filter(Boolean).length,\n          byTool: toolsRes.map((r) => ({ key: r._id || '(none)', calls: r.calls, errors: r.errors })),\n          byUser: usersRes.map((r) => ({ key: r._id || '(none)', calls: r.calls, errors: r.errors })),\n          bySystem: systemsRes.map((r) => ({ key: r._id || '(none)', calls: r.calls, errors: r.errors })),\n          hourly: hourlyRes.map((r) => ({ hour: r._id, calls: r.calls, errors: r.errors })),\n          events: eventsRes,\n        }\n      } catch (err) {\n        d2.state.stats = d2.state.stats || { total: 0, errors: 0, users: 0, systems: 0, byTool: [], byUser: [], bySystem: [], hourly: [], events: [] }\n        d2.state.fetchError = err?.message || String(err)\n      }\n      d2.state.loading = false\n    }\n\n    const setFilter = (next) => {\n      d2.state.filter = next\n      refetch()\n    }\n\n    d2.on('[data-filter-type]', 'click', (e, el) => {\n      const type = el.dataset.filterType\n      const value = el.dataset.filterValue\n      const current = d2.state.filter || {}\n      setFilter({ ...current, [type]: current[type] === value ? null : value })\n    })\n    d2.on('[data-clear]', 'click', (e, el) => {\n      const which = el.dataset.clear\n      if (which === 'all') {\n        setFilter({})\n      } else {\n        const current = { ...(d2.state.filter || {}) }\n        delete current[which]\n        setFilter(current)\n      }\n    })\n    d2.on('[data-clear-toggle-errors]', 'click', () => {\n      const current = d2.state.filter || {}\n      setFilter({ ...current, onlyErrors: !current.onlyErrors })\n    })\n    d2.on('[data-expand-toggle]', 'click', (e, el) => {\n      const key = el.dataset.expandToggle\n      const current = d2.state.expanded || {}\n      d2.state.expanded = { ...current, [key]: !current[key] }\n    })\n\n    refetch()\n  },\n}"}},"dataset":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"dataset"}}}}}}}}}},{"_id":"5ed9bed7b9e0891ce913e884","component":"data2-core-types@Component","params":{"package":"data2-core","component":"DataSource","renderable":{"dimensions":{"disabled":false,"component":"data2-core-types@Dimensions","params":{"width":1366,"exactWidth":false,"exactHeight":false,"height":768}}}}},{"_id":"5f472ae463c680de4ff296e9","component":"data2-core-types@Component","params":{"package":"data2-core","component":"Data2TableDataSource","extends":"data2-core@DataSource","renderable":{"dimensions":{"disabled":false,"component":"data2-core-types@Dimensions","params":{"width":1366,"exactWidth":false,"exactHeight":false,"height":768}}}}}]}},{"reference":"ExternalComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"_id":"5f060d9b1ca96def42f3c40a","displayName":"Builder AuthStrategy","component":"data2-core@AuthenticationStrategy","system":"5e3b796d6228227ca637d0f4","params":{"credentials":[{"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"status"}}],"verifier":{"component":"data2-core-types@DataSetReference","params":{"reference":"UsersDataSet"}},"sessionShared":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"password":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},"email":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},"resetPassword":{"resetEmail":{"artboard":{"params":{"preventEvaluation":true,"reference":"nR6Q9d7qdaPtZhJ28Q8Dy"},"component":"data2-core-types@ArtboardReference"}},"resetSuccessEmail":{"artboard":{"params":{"preventEvaluation":true,"reference":"yPCJBTKo8q1Mw0B_3Kpwl"},"component":"data2-core-types@ArtboardReference"}}},"session":[{"component":"data2-core-types@DataSetColumnReference","params":{"column":"name"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"status"}}],"sessionMetadata":{"params":{"actions":[{"params":{"compare":{"params":{"subject":{"params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},{"params":{"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":"active"}},"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user.status"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is active user"}]},"component":"data2-core-logical-operators@And","displayName":"is active and has _id"}},"component":"data2-core-logical-operators@Not"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check $user"},{"params":{"action":{"params":{"pattern":{"component":"data2-core-primitives@String","params":{"content":"@data2.app"}},"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user.email"}}}}},"component":"data2-core-functions@Includes","displayName":"isData2User"},"resultName":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}},"component":"data2-core-flow@Step"},{"params":{"action":{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.d2_app"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"management"}}]},"component":"data2-core-functions@Includes","displayName":"isData2App Exception"},"resultName":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}},"component":"data2-core-flow@Step"},{"params":{"resultName":{"component":"data2-core-primitives@String","params":{"content":"has_access"}},"action":{"params":{"compare":{"params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}}},{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}}}]},"component":"data2-core-logical-operators@Or"},"else":{"params":{"actions":[{"params":{"actions":[{"params":{"compare":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}},"component":"data2-core-logical-operators@Not"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check $metadata.system"},{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":"filter","args":[{"_id":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}}]},"component":"data2-core-types@Interaction"},{"params":{"compare":{"params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records.length"}}}}},"component":"data2-core-logical-operators@Not","displayName":"systems not found"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check system found"},{"params":{"actions":[{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":"filter","args":[{"user":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},"organization":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"cursor.current.organization._id"}}}}}]},"component":"data2-core-types@Interaction"},{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":"filter","args":[{"user":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},"system":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}}]},"component":"data2-core-types@Interaction"}]},"component":"data2-core-flow@Parallel"}]},"component":"data2-core-flow@Series","displayName":"common setup"},{"params":{"then":{"params":{"content":true},"component":"data2-core-primitives@Boolean"},"else":{"params":{"content":false},"component":"data2-core-primitives@Boolean"},"compare":{"params":{"components":{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"mapper":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"system"}}],"body":{"params":{"expression":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.visibility"}}}},"defaultCase":{"params":{"content":false},"component":"data2-core-primitives@Boolean"},"cases":[{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-primitives@String","params":{"content":"public"}},"value":{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"owner"}},{"component":"data2-core-primitives@String","params":{"content":"billing-owner"}},{"component":"data2-core-primitives@String","params":{"content":"admin"}},{"component":"data2-core-primitives@String","params":{"content":"member"}}]},"component":"data2-core-functions@Includes","displayName":"has role with access"}]},"component":"data2-core-logical-operators@And","displayName":"has org member role with access"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is org member"},{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":"collaborator"}}},"component":"data2-core-comparison-operators@Equal","displayName":"is collaborator"}]},"component":"data2-core-logical-operators@And","displayName":"is org member and collaborator"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is collaborator"},{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"access"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"access.system._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"has system access"}]},"component":"data2-core-logical-operators@And","displayName":"is collaborator and has system access"}]},"component":"data2-core-logical-operators@Or"}}},{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-primitives@String","params":{"content":"private"}},"value":{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"owner"}},{"component":"data2-core-primitives@String","params":{"content":"admin"}}]},"component":"data2-core-functions@Includes","displayName":"is owner/admin"}]},"component":"data2-core-logical-operators@And","displayName":"has org member role with access"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is owner/admin"},{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is org member"},{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"access"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"access.system._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"has system access"}]},"component":"data2-core-logical-operators@And","displayName":"is member and has system access"}]},"component":"data2-core-logical-operators@Or","displayName":"is owner/admin or has system access"}}}]},"component":"data2-core-flow@Switch"}}}},"component":"data2-core-functions@ArrayMap"}},"component":"data2-core-logical-operators@And","displayName":"has org member for all systems in request"}},"component":"data2-core-flow@If"}]},"component":"data2-core-flow@Series"},"then":{"params":{"content":true},"component":"data2-core-primitives@Boolean"}},"component":"data2-core-flow@If"}},"component":"data2-core-flow@Step"},{"params":{"then":{"system":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}},"else":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"},"compare":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"has_access"}}}}},"component":"data2-core-flow@If"}]},"component":"data2-core-flow@Series"},"sessionExpiresIn":{"component":"data2-core-primitives@Number","params":{"content":604800}},"sessionRenewal":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"identityProviders":[{"provider":{"component":"data2-core-primitives@String","params":{"content":"GOOGLE"}},"clientId":{"component":"data2-core-primitives@String","params":{"content":"55470861603-22pvfc1t49lp8cjnbfk71s5ct9hp1q1v.apps.googleusercontent.com"}}}]},"reference":"Data2BuilderAuthentication","updatedAt":"2026-08-06T19:31:23.557Z"},{"_id":"5f060ee51ca96def42f3fbd1","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"UsersTableDataSource"}},"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}}},"reference":"UsersDataSet","updatedAt":"2026-03-04T21:16:40.291Z"},{"_id":"68f938cf5fb002e33752a43d","displayName":"InternalApplicationsAuthenticationStrategy","component":"data2-core@AuthenticationStrategy","system":"5e3b796d6228227ca637d0f4","params":{"resetPassword":{"resetEmail":{"artboard":{"params":{"preventEvaluation":true},"component":"data2-core-types@ArtboardReference"}},"resetSuccessEmail":{"artboard":{"params":{"preventEvaluation":true},"component":"data2-core-types@ArtboardReference"}}},"verifier":{"disabled":false,"component":"data2-core-types@DataSetReference","params":{"reference":"InternalApplicationsVerifierDataSet"}},"password":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"secret"}},"credentials":[{"component":"data2-core-types@FieldReference","params":{"key":"application"}},{"component":"data2-core-types@FieldReference","params":{"key":"secret"}},{"component":"data2-core-types@FieldReference","params":{"key":"status"}}],"session":[{"component":"data2-core-types@FieldReference","params":{"key":"application"}},{"component":"data2-core-types@FieldReference","params":{"key":"secret"}},{"component":"data2-core-types@FieldReference","params":{"key":"status"}}]},"reference":"InternalApplicationsAuthenticationStrategy","updatedAt":"2025-10-22T20:08:54.442Z","createdAt":"2025-10-22T20:04:31.198Z"},{"component":"data2-core@DataSet","reference":"SessionsDataSet","params":{"requiresConfirmation":false,"pk":"key","datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"data2sessionsdatasource"}}}},{"reference":"UsersTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@ServerSessionsDataSource","reference":"data2sessionsdatasource","params":{}},{"_id":"5f1600b70528b92601890f75","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ServiceComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ServiceComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:20.208Z","createdAt":"2020-07-20T20:38:15.436Z"},{"_id":"5f1602190528b92601890f7d","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":40000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentInstancesTableDataSource"}},"sort":{"_id":1},"pk":"_id","autoEdit":true,"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:07.089Z","createdAt":"2020-07-20T20:44:09.350Z"},{"_id":"5f16017f0528b92601890f7a","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"clientApplicationDomain"}}},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"FileComponentInstancesDataSet","updatedAt":"2023-08-03T16:08:18.193Z","createdAt":"2020-07-20T20:41:35.797Z"},{"_id":"5f1601990528b92601890f7b","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ApplicationsTableDataSource"}},"pk":"_id","autoEdit":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"params":{"column":"_id"},"component":"data2-core-types@DataSetColumnReference"}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"ApplicationsDataSet","updatedAt":"2022-12-13T21:51:13.995Z","createdAt":"2020-07-20T20:42:01.657Z"},{"_id":"5f16172a0528b92601890f85","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":10000}}},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"DataComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"DataComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:12.831Z","createdAt":"2020-07-20T22:14:02.097Z"},{"_id":"60ddc1bbda3861ca65407c5a","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"clientApplicationDomain"}}},"pagination":{"size":1},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"}},"reference":"OneFileComponentInstancesDataSet","updatedAt":"2022-02-09T19:44:38.036Z","createdAt":"2020-07-20T20:41:35.797Z"},{"_id":"63ee3d38b8c9838c62fb05fb","displayName":"DriveFileComponentInstancesDataSet","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core@Drive"}}},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"DriveFileComponentInstancesDataSet","updatedAt":"2025-12-04T21:58:32.367Z","createdAt":"2023-02-16T14:27:07.797Z"},{"reference":"ServiceComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6a74046e5bcb322df2e7c4b5","component":"data2-rush@HTTPListener","reference":"flightMcpAgentLoop","system":"69f8a1f302514a1d6508bdbc","params":{}},{"_id":"6a74126bdad5912765089c13","component":"data2-rush@HTTPListener","reference":"mcpConnectionStatus","system":"69f8a1f302514a1d6508bdbc","params":{}},{"_id":"6a740a66f08aa56d3e04e199","component":"data2-rush@HTTPListener","reference":"mcpDiscoverTools","system":"69f8a1f302514a1d6508bdbc","params":{}},{"_id":"6a74126c669cd00c3487b759","component":"data2-rush@HTTPListener","reference":"mcpOauthExchange","system":"69f8a1f302514a1d6508bdbc","params":{}},{"_id":"6a753e3a9f1ece2343b4a554","component":"data2-rush@HTTPListener","reference":"harnessGetMessages","system":"69f8a1f302514a1d6508bdbc","params":{}},{"_id":"6a7536f1079628f116ca648c","component":"data2-rush@HTTPListener","reference":"harnessAsk","system":"69f8a1f302514a1d6508bdbc","params":{}},{"_id":"6a7536f391fcc12ded021f3d","component":"data2-rush@HTTPListener","reference":"harnessListSessions","system":"69f8a1f302514a1d6508bdbc","params":{}}]}},{"reference":"ComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6a740c347b69f6e94451ce76","component":"data2-core-primitives@Router","system":"69f8a1f302514a1d6508bdbc","displayName":"Flight MCP Router","params":{"routerType":{"component":"data2-core-primitives@String","params":{"content":"browser"}},"routes":[{"component":"data2-core-primitives@Route","params":{"path":"","name":"Flight MCP Chat","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"o5qF8lLmjVIINZgGI_kBY"}}}},{"component":"data2-core-primitives@Route","params":{"path":"/admin","name":"MCP Servers Admin","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"ZdwbcVhrs57jy72_hWXOG"}},"policies":[{"component":"data2-core-auth@Policy","params":{"authenticationStrategy":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"mcpAdminAuth"}}}}]}},{"component":"data2-core-primitives@Route","params":{"path":"/admin/oauth-callback","name":"MCP OAuth Callback","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"RX9wuE0VzWu1TV1BydA3h"}}}},{"component":"data2-core-primitives@Route","params":{"path":"/mock-idp/authorize","name":"Mock IdP Authorize","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"e-ZF97cPJ1fyaCLUR9psy"}}}},{"component":"data2-core-primitives@Route","params":{"path":"/harness","name":"Harness Chat","content":{"component":"data2-core-types@ArtboardReference","params":{"reference":"SvSo8peBnLvGaepvp4777"}}}}],"login":{"component":"data2-core-types@ArtboardReference","params":{"reference":"i0EjOBt0XvGVuEIPQQX-J"}}},"reference":"flightMcpRouter"},{"_id":"6a740d9390f4048f4429a1ee","component":"data2-core-primitives@Artboard","system":"69f8a1f302514a1d6508bdbc","displayName":"Admin Login","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Admin Login"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"i0EjOBt0XvGVuEIPQQX-J"},{"_id":"6a753ef1464ed66661361737","component":"data2-core-primitives@Artboard","system":"69f8a1f302514a1d6508bdbc","displayName":"Harness Chat","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Harness Chat"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"SvSo8peBnLvGaepvp4777"},{"_id":"6a742295669cd00c3487c648","component":"data2-core-primitives@Artboard","system":"69f8a1f302514a1d6508bdbc","displayName":"Mock OAuth Authorize","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Mock OAuth Authorize"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"e-ZF97cPJ1fyaCLUR9psy"},{"_id":"6a74126b90f4048f4429a847","component":"data2-core-primitives@Artboard","system":"69f8a1f302514a1d6508bdbc","displayName":"MCP OAuth Callback","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"MCP OAuth Callback"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"RX9wuE0VzWu1TV1BydA3h"},{"_id":"6a740a689754f002640b799a","component":"data2-core-primitives@Artboard","system":"69f8a1f302514a1d6508bdbc","displayName":"MCP Servers Admin","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"MCP Servers Admin"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"ZdwbcVhrs57jy72_hWXOG"},{"_id":"6a74046c9b80399cc1ea7a3e","component":"data2-core-primitives@Artboard","system":"69f8a1f302514a1d6508bdbc","displayName":"MCP Client Demo — Flight Search","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"MCP Client Demo — Flight Search"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"o5qF8lLmjVIINZgGI_kBY"},{"_id":"e08ff46e202af2a6f36af6a8","parent":"6a740d9390f4048f4429a1ee","component":"pliskin@mcpAdminLogin","system":"69f8a1f302514a1d6508bdbc","displayName":"McpAdminLoginInstance","params":{"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}}},"authStrategy":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"mcpAdminAuth"}}},"reference":"0JP-HJOU5haHMWGyXvhgT"},{"_id":"86413152b58de904939cc562","parent":"6a753ef1464ed66661361737","component":"pliskin@harnessChatShell","system":"69f8a1f302514a1d6508bdbc","displayName":"Harness Chat Shell Instance","params":{"ui":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"harnessUiStore"}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}}}},"reference":"4W5Y-0QSaLo9-WhJbM1BR"},{"_id":"c241d39f71126562ad7366da","parent":"6a742295669cd00c3487c648","component":"pliskin@mockOauthAuthorize","system":"69f8a1f302514a1d6508bdbc","displayName":"MockOauthAuthorizeInstance","params":{"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}}},"codesDataset":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"mock-oauth-codesDataSet"}}},"reference":"aM-7JIeBdcG07Tb9pvr2X"},{"_id":"8bc14d825e05b2357a5cc2e5","parent":"6a74126b90f4048f4429a847","component":"pliskin@mcpOauthCallback","system":"69f8a1f302514a1d6508bdbc","displayName":"McpOauthCallbackInstance","params":{"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}}}},"reference":"C4dzevPd9rPyQn0kcggED"},{"_id":"7475349894d1211485dbd51c","parent":"6a740a689754f002640b799a","component":"pliskin@mcpServersAdmin","system":"69f8a1f302514a1d6508bdbc","displayName":"McpServersAdminInstance","params":{"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}}},"authStrategy":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"mcpAdminAuth"}}},"reference":"a2Z5fpkfdrZPPArXwOae1"},{"_id":"79b87ddf2b93457677b8f2ee","parent":"6a74046c9b80399cc1ea7a3e","component":"pliskin@flightMcpChat","system":"69f8a1f302514a1d6508bdbc","displayName":"FlightMcpChatInstance","params":{"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}}}},"reference":"c5K73Huo_9mVVzCEFuWL7"}]}},{"_id":"5fc4faeec8da12be8bf3d08a","component":"data2-core@Data2TableDataSource","system":"5e3b796d6228227ca637d0f4","params":{"paginate":{"default":1000},"super":{},"table":"fileComponentInstances","schema":[{"component":"data2-core-types@Field","params":{"key":"component","title":"Component","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"system","title":"System","component":"data2-core-primitives@ObjectId"}},{"component":"data2-core-types@Field","params":{"key":"displayName","title":"Display Name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"params","title":"Params","component":"data2-core-primitives@Object"}},{"component":"data2-core-types@Field","params":{"key":"reference","title":"Reference","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"fileId"}},"title":"File ID","component":"data2-core-primitives@ObjectId"},"break":true}],"hooks":{"before":{"all":[{"hook":"softDelete"}],"find":[{"hook":"useCache","options":{"additionalGroupKeys":["$and.0.system","$and.1.system"],"skipCache":true}}],"create":[{"hook":"timestamp","options":{"fields":["createdAt","updatedAt"]}}],"update":[{"hook":"timestamp","options":{"fields":["updatedAt"]}}],"patch":[{"hook":"timestamp","options":{"fields":["updatedAt"]}}]},"after":{"all":[{"hook":"fileUrl","options":{"downloadField":"params.fileUrl","uploadField":"params.uploadFileUrl","enhanceSchema":false}}],"find":[{"hook":"useCache","options":{"additionalGroupKeys":["$and.0.system","$and.1.system"],"skipCache":true}}],"create":[{"hook":"invalidateCache","options":{"additionalGroupKeys":["system"],"secondaryUniqueKeys":["reference"]}},{"hook":"invalidateEnvCache"}],"update":[{"hook":"invalidateCache","options":{"additionalGroupKeys":["system"],"secondaryUniqueKeys":["reference"]}},{"hook":"invalidateEnvCache"}],"patch":[{"hook":"invalidateCache","options":{"additionalGroupKeys":["system"],"secondaryUniqueKeys":["reference"]}},{"hook":"invalidateEnvCache"}],"remove":[{"hook":"invalidateCache","options":{"additionalGroupKeys":["system"],"secondaryUniqueKeys":["reference"]}},{"hook":"invalidateEnvCache"}]}},"multi":["create"],"useEstimatedDocumentCount":true},"reference":"FileComponentInstancesTableDataSource","updatedAt":"2022-12-19T20:42:51.837Z","createdAt":"2020-11-30T13:59:52.294Z"},{"reference":"ApplicationsTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6a74059bd5c61d2c1c9ab6b7","displayName":"Flight MCP Chat Demo","reference":"dUbQg8Sckjdkw003LUmMZ","params":{"domain":{"component":"data2-core-primitives@String","params":{"content":"flight-mcp"}},"entryPoint":{"component":"data2-core-types@ComponentInstanceReference","params":{"component":"data2-core-primitives@Router","reference":"flightMcpRouter"}}},"system":"69f8a1f302514a1d6508bdbc","component":"data2-core-primitives@Application"}]}},{"reference":"DataComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6a740a62d5a555faccfdafea","component":"data2-core@DataSet","system":"69f8a1f302514a1d6508bdbc","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"_ziKSflmzxQR07d7vxg66"}}},"reference":"_ziKSflmzxQR07d7vxg66DataSet"},{"_id":"6a740a629b80399cc1ea83cc","component":"data2-core@Data2TableDataSource","system":"69f8a1f302514a1d6508bdbc","params":{"table":"_ziKSflmzxQR07d7vxg66","schema":[{"component":"data2-core-types@Field","params":{"key":"name","title":"Name","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"endpointUrl","title":"Endpoint URL","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"description","title":"Description","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"catalogText","title":"Catalog Text","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"active","title":"Active","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"key":"createdAt","title":"Created At","component":"data2-core-primitives@Date"}},{"component":"data2-core-types@Field","params":{"key":"authHeaderName","title":"Auth Header Name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"authHeaderValue","title":"Auth Header Value","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"authType","title":"Auth Type","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"oauthClientId","title":"OAuth Client ID","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"oauthClientSecret","title":"OAuth Client Secret","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"oauthAuthorizeUrl","title":"OAuth Authorize URL","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"oauthTokenUrl","title":"OAuth Token URL","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"oauthScopes","title":"OAuth Scopes","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"oauthAccessToken","title":"OAuth Access Token","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"oauthRefreshToken","title":"OAuth Refresh Token","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"oauthExpiresAt","title":"OAuth Expires At","component":"data2-core-primitives@Date"}}]},"reference":"_ziKSflmzxQR07d7vxg66"},{"_id":"6a741055d5a555faccfdb7a4","component":"data2-core-auth@CustomAuthenticationStrategy","system":"69f8a1f302514a1d6508bdbc","params":{},"reference":"mcpAdminAuth"},{"_id":"6a753eb4dc05e47d0b3498c3","component":"data2-core@Store","system":"69f8a1f302514a1d6508bdbc","params":{"initialData":{"activeSessionId":"","mood":"calm","moodIllustrationUrl":"","liveTrace":[],"isBusy":false,"messagesVersion":0}},"reference":"harnessUiStore"},{"_id":"6a74229152f7312695b9c7cf","component":"data2-core@DataSet","system":"69f8a1f302514a1d6508bdbc","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"mock-oauth-codes"}}},"reference":"mock-oauth-codesDataSet"},{"_id":"6a742291dad591276508ac2f","component":"data2-core@Data2TableDataSource","system":"69f8a1f302514a1d6508bdbc","params":{"table":"mock-oauth-codes","schema":[{"component":"data2-core-types@Field","params":{"key":"code","title":"Code","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"codeChallenge","title":"Code Challenge","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"clientId","title":"Client ID","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"redirectUri","title":"Redirect URI","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"used","title":"Used","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"key":"createdAt","title":"Created At","component":"data2-core-primitives@Date"}}]},"reference":"mock-oauth-codes"}]}},{"reference":"BundlesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}}],"processesParams":{}}}}