@corva/ui 3.80.0-3 → 3.80.0-5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs-bundle/components/EmojiIconButton.js +1 -1
- package/cjs-bundle/components/EmojiIconButton.js.map +1 -1
- package/components/EmojiIconButton.d.ts.map +1 -1
- package/components/EmojiIconButton.js +1 -1
- package/components/EmojiIconButton.js.map +1 -1
- package/mcp-server/server.mjs +161 -20
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var e=require("@babel/runtime/helpers/slicedToArray"),t=require("react"),i=require("emoji-mart"),o=require("prop-types"),r=require("@material-ui/core/Popover"),n=require("./IconButton/index.js"),l=require("./Icons/EmojiIcon.js"),
|
|
1
|
+
"use strict";var e=require("@babel/runtime/helpers/slicedToArray"),t=require("react"),i=require("emoji-mart"),o=require("prop-types"),r=require("@material-ui/core/Popover"),n=require("@material-ui/core/Fade"),a=require("./IconButton/index.js"),l=require("./Icons/EmojiIcon.js"),u=require("react/jsx-runtime");function d(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var s=d(e),c=d(o),p=d(r),m=d(n),f={title:"Add Emoji"};function j(e){var o=e.handleSelectEmoji,r=e.emojiIconClassName,n=void 0===r?void 0:r,d=e.disableRipple,c=void 0!==d&&d,j=e.closeOnSelect,v=void 0===j||j,h=e["data-testid"],b=void 0===h?"generic_emojiButton":h,q=e.tooltipProps,g=void 0===q?f:q,x=e.icon,E=void 0===x?void 0:x,R=t.useState(!1),S=s.default(R,2),C=S[0],I=S[1],P=t.useRef(null);return u.jsxs(u.Fragment,{children:[u.jsx(a,{"data-testid":b,buttonRef:function(e){P.current=e},"aria-label":"Emoji",onClick:function(){return I(!0)},disableRipple:c,className:n,tooltipProps:g,children:E||u.jsx(l,{})}),u.jsx(p.default,{open:C,TransitionComponent:m.default,anchorEl:P.current,onClose:function(){return I(!1)},anchorOrigin:{vertical:"bottom",horizontal:"right"},transformOrigin:{vertical:"top",horizontal:"right"},children:u.jsx(i.Picker,{onSelect:function(e){o(e),v&&I(!1)},theme:"dark"})})]})}j.propTypes={handleSelectEmoji:c.default.func.isRequired,emojiIconClassName:c.default.string,disableRipple:c.default.bool,closeOnSelect:c.default.bool,"data-testid":c.default.string,tooltipProps:c.default.shape({}),icon:c.default.node};var v=t.memo(j);module.exports=v;
|
|
2
2
|
//# sourceMappingURL=EmojiIconButton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmojiIconButton.js","sources":["../../../src/components/EmojiIconButton.js"],"sourcesContent":["import { memo, useRef, useState } from 'react';\nimport { Picker } from 'emoji-mart';\nimport PropTypes from 'prop-types';\nimport Popover from '@material-ui/core/Popover';\n\nimport IconButton from '~components/IconButton';\nimport EmojiIcon from '~components/Icons/EmojiIcon';\n\nconst defaultTooltipProps = { title: 'Add Emoji' };\n\n/** @param {any} props Preserve the legacy component's permissive public prop type. */\nfunction EmojiIconButton({\n handleSelectEmoji,\n emojiIconClassName = undefined,\n disableRipple = false,\n closeOnSelect = true,\n 'data-testid': testId = 'generic_emojiButton',\n tooltipProps = defaultTooltipProps,\n icon = undefined,\n}) {\n const [openEmojiPicker, setOpenEmojiPicker] = useState(false);\n const anchorEl = useRef(null);\n\n const onSelect = emoji => {\n handleSelectEmoji(emoji);\n if (closeOnSelect) {\n setOpenEmojiPicker(false);\n }\n };\n\n return (\n <>\n <IconButton\n data-testid={testId}\n buttonRef={node => {\n anchorEl.current = node;\n }}\n aria-label=\"Emoji\"\n onClick={() => setOpenEmojiPicker(true)}\n disableRipple={disableRipple}\n className={emojiIconClassName}\n tooltipProps={tooltipProps}\n >\n {icon || <EmojiIcon />}\n </IconButton>\n\n <Popover\n open={openEmojiPicker}\n anchorEl={anchorEl.current}\n onClose={() => setOpenEmojiPicker(false)}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'right',\n }}\n transformOrigin={{\n vertical: 'top',\n horizontal: 'right',\n }}\n >\n <Picker onSelect={onSelect} theme=\"dark\" />\n </Popover>\n </>\n );\n}\n\nEmojiIconButton.propTypes = {\n handleSelectEmoji: PropTypes.func.isRequired,\n emojiIconClassName: PropTypes.string,\n disableRipple: PropTypes.bool,\n closeOnSelect: PropTypes.bool,\n 'data-testid': PropTypes.string,\n tooltipProps: PropTypes.shape({}),\n icon: PropTypes.node,\n};\n\nexport default memo(EmojiIconButton);\n"],"names":["defaultTooltipProps","title","EmojiIconButton","_ref","handleSelectEmoji","_ref$emojiIconClassNa","emojiIconClassName","undefined","_ref$disableRipple","disableRipple","_ref$closeOnSelect","closeOnSelect","_ref$dataTestid","testId","_ref$tooltipProps","tooltipProps","_ref$icon","icon","useState","_useState2","_slicedToArray","_useState","openEmojiPicker","setOpenEmojiPicker","anchorEl","useRef","_jsxs","_Fragment","children","_jsx","IconButton","buttonRef","node","current","onClick","className","EmojiIcon","Popover","open","onClose","anchorOrigin","vertical","horizontal","transformOrigin","Picker","onSelect","emoji","theme","propTypes","PropTypes","func","isRequired","string","bool","shape","memo"],"mappings":"
|
|
1
|
+
{"version":3,"file":"EmojiIconButton.js","sources":["../../../src/components/EmojiIconButton.js"],"sourcesContent":["import { memo, useRef, useState } from 'react';\nimport { Picker } from 'emoji-mart';\nimport PropTypes from 'prop-types';\nimport Popover from '@material-ui/core/Popover';\nimport Fade from '@material-ui/core/Fade';\n\nimport IconButton from '~components/IconButton';\nimport EmojiIcon from '~components/Icons/EmojiIcon';\n\nconst defaultTooltipProps = { title: 'Add Emoji' };\n\n/** @param {any} props Preserve the legacy component's permissive public prop type. */\nfunction EmojiIconButton({\n handleSelectEmoji,\n emojiIconClassName = undefined,\n disableRipple = false,\n closeOnSelect = true,\n 'data-testid': testId = 'generic_emojiButton',\n tooltipProps = defaultTooltipProps,\n icon = undefined,\n}) {\n const [openEmojiPicker, setOpenEmojiPicker] = useState(false);\n const anchorEl = useRef(null);\n\n const onSelect = emoji => {\n handleSelectEmoji(emoji);\n if (closeOnSelect) {\n setOpenEmojiPicker(false);\n }\n };\n\n return (\n <>\n <IconButton\n data-testid={testId}\n buttonRef={node => {\n anchorEl.current = node;\n }}\n aria-label=\"Emoji\"\n onClick={() => setOpenEmojiPicker(true)}\n disableRipple={disableRipple}\n className={emojiIconClassName}\n tooltipProps={tooltipProps}\n >\n {icon || <EmojiIcon />}\n </IconButton>\n\n <Popover\n open={openEmojiPicker}\n TransitionComponent={Fade}\n anchorEl={anchorEl.current}\n onClose={() => setOpenEmojiPicker(false)}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'right',\n }}\n transformOrigin={{\n vertical: 'top',\n horizontal: 'right',\n }}\n >\n <Picker onSelect={onSelect} theme=\"dark\" />\n </Popover>\n </>\n );\n}\n\nEmojiIconButton.propTypes = {\n handleSelectEmoji: PropTypes.func.isRequired,\n emojiIconClassName: PropTypes.string,\n disableRipple: PropTypes.bool,\n closeOnSelect: PropTypes.bool,\n 'data-testid': PropTypes.string,\n tooltipProps: PropTypes.shape({}),\n icon: PropTypes.node,\n};\n\nexport default memo(EmojiIconButton);\n"],"names":["defaultTooltipProps","title","EmojiIconButton","_ref","handleSelectEmoji","_ref$emojiIconClassNa","emojiIconClassName","undefined","_ref$disableRipple","disableRipple","_ref$closeOnSelect","closeOnSelect","_ref$dataTestid","testId","_ref$tooltipProps","tooltipProps","_ref$icon","icon","useState","_useState2","_slicedToArray","_useState","openEmojiPicker","setOpenEmojiPicker","anchorEl","useRef","_jsxs","_Fragment","children","_jsx","IconButton","buttonRef","node","current","onClick","className","EmojiIcon","Popover","open","TransitionComponent","Fade","onClose","anchorOrigin","vertical","horizontal","transformOrigin","Picker","onSelect","emoji","theme","propTypes","PropTypes","func","isRequired","string","bool","shape","memo"],"mappings":"6ZASMA,EAAsB,CAAEC,MAAO,aAGrC,SAASC,EAQNC,GAAA,IAPDC,IAAAA,kBAAiBC,EAAAF,EACjBG,mBAAAA,kBAAqBC,EAASF,EAAAG,EAAAL,EAC9BM,cAAAA,cAAqBD,EAAAE,EAAAP,EACrBQ,cAAAA,cAAoBD,EAAAE,EAAAT,EACpB,eAAeU,aAAS,sBAAqBD,EAAAE,EAAAX,EAC7CY,aAAAA,aAAef,EAAmBc,EAAAE,EAAAb,EAClCc,KAAAA,kBAAOV,EAASS,EAE8BE,EAAAA,EAAQA,UAAC,GAAMC,EAAAC,EAAAA,QAAAC,EAAA,GAAtDC,EAAeH,EAAA,GAAEI,EAAkBJ,EAAA,GACpCK,EAAWC,SAAO,MASxB,OACEC,EAAAA,KAAAC,EAAAA,SAAA,CAAAC,SAAA,CACEC,MAACC,EAAU,CACT,cAAajB,EACbkB,UAAW,SAAAC,GACTR,EAASS,QAAUD,CACnB,EACF,aAAW,QACXE,QAAS,WAAA,OAAMX,GAAmB,EAAM,EACxCd,cAAeA,EACf0B,UAAW7B,EACXS,aAAcA,EAAaa,SAE1BX,GAAQY,MAACO,EAAS,CAAA,KAGrBP,MAACQ,UAAO,CACNC,KAAMhB,EACNiB,oBAAqBC,EAAK,QAC1BhB,SAAUA,EAASS,QACnBQ,QAAS,WAAA,OAAMlB,GAAmB,EAAO,EACzCmB,aAAc,CACZC,SAAU,SACVC,WAAY,SAEdC,gBAAiB,CACfF,SAAU,MACVC,WAAY,SACZhB,SAEFC,MAACiB,SAAM,CAACC,SArCG,SAAAC,GACf5C,EAAkB4C,GACdrC,GACFY,GAAmB,IAkCW0B,MAAM,aAI1C,CAEA/C,EAAgBgD,UAAY,CAC1B9C,kBAAmB+C,EAAAA,QAAUC,KAAKC,WAClC/C,mBAAoB6C,EAAS,QAACG,OAC9B7C,cAAe0C,EAAS,QAACI,KACzB5C,cAAewC,EAAS,QAACI,KACzB,cAAeJ,EAAS,QAACG,OACzBvC,aAAcoC,EAAAA,QAAUK,MAAM,IAC9BvC,KAAMkC,EAAS,QAACnB,MAGlB,IAAeyB,EAAAA,EAAAA,KAAKvD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmojiIconButton.d.ts","sourceRoot":"","sources":["../../src/components/EmojiIconButton.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"EmojiIconButton.d.ts","sourceRoot":"","sources":["../../src/components/EmojiIconButton.js"],"names":[],"mappings":"AAWA,sFAAsF;AACtF,iBAAS,eAAe,CAAC,EACvB,iBAAiB,EACjB,kBAA8B,EAC9B,aAAqB,EACrB,aAAoB,EACpB,aAAa,EAAE,MAA8B,EAC7C,YAAkC,EAClC,IAAgB,GACjB,EATW,GASX,+BA6CA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import o from"@babel/runtime/helpers/slicedToArray";import{memo as i,useState as e,useRef as
|
|
1
|
+
import o from"@babel/runtime/helpers/slicedToArray";import{memo as i,useState as e,useRef as r}from"react";import{Picker as t}from"emoji-mart";import n from"prop-types";import a from"@material-ui/core/Popover";import l from"@material-ui/core/Fade";import m from"./IconButton/index.js";import c from"./Icons/EmojiIcon.js";import{jsxs as p,Fragment as s,jsx as d}from"react/jsx-runtime";var u={title:"Add Emoji"};function f(i){var n=i.handleSelectEmoji,f=i.emojiIconClassName,h=void 0===f?void 0:f,v=i.disableRipple,j=void 0!==v&&v,b=i.closeOnSelect,g=void 0===b||b,E=i["data-testid"],C=void 0===E?"generic_emojiButton":E,I=i.tooltipProps,R=void 0===I?u:I,S=i.icon,O=void 0===S?void 0:S,P=e(!1),x=o(P,2),y=x[0],N=x[1],T=r(null);return p(s,{children:[d(m,{"data-testid":C,buttonRef:function(o){T.current=o},"aria-label":"Emoji",onClick:function(){return N(!0)},disableRipple:j,className:h,tooltipProps:R,children:O||d(c,{})}),d(a,{open:y,TransitionComponent:l,anchorEl:T.current,onClose:function(){return N(!1)},anchorOrigin:{vertical:"bottom",horizontal:"right"},transformOrigin:{vertical:"top",horizontal:"right"},children:d(t,{onSelect:function(o){n(o),g&&N(!1)},theme:"dark"})})]})}f.propTypes={handleSelectEmoji:n.func.isRequired,emojiIconClassName:n.string,disableRipple:n.bool,closeOnSelect:n.bool,"data-testid":n.string,tooltipProps:n.shape({}),icon:n.node};var h=i(f);export{h as default};
|
|
2
2
|
//# sourceMappingURL=EmojiIconButton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmojiIconButton.js","sources":["../../src/components/EmojiIconButton.js"],"sourcesContent":["import { memo, useRef, useState } from 'react';\nimport { Picker } from 'emoji-mart';\nimport PropTypes from 'prop-types';\nimport Popover from '@material-ui/core/Popover';\n\nimport IconButton from '~components/IconButton';\nimport EmojiIcon from '~components/Icons/EmojiIcon';\n\nconst defaultTooltipProps = { title: 'Add Emoji' };\n\n/** @param {any} props Preserve the legacy component's permissive public prop type. */\nfunction EmojiIconButton({\n handleSelectEmoji,\n emojiIconClassName = undefined,\n disableRipple = false,\n closeOnSelect = true,\n 'data-testid': testId = 'generic_emojiButton',\n tooltipProps = defaultTooltipProps,\n icon = undefined,\n}) {\n const [openEmojiPicker, setOpenEmojiPicker] = useState(false);\n const anchorEl = useRef(null);\n\n const onSelect = emoji => {\n handleSelectEmoji(emoji);\n if (closeOnSelect) {\n setOpenEmojiPicker(false);\n }\n };\n\n return (\n <>\n <IconButton\n data-testid={testId}\n buttonRef={node => {\n anchorEl.current = node;\n }}\n aria-label=\"Emoji\"\n onClick={() => setOpenEmojiPicker(true)}\n disableRipple={disableRipple}\n className={emojiIconClassName}\n tooltipProps={tooltipProps}\n >\n {icon || <EmojiIcon />}\n </IconButton>\n\n <Popover\n open={openEmojiPicker}\n anchorEl={anchorEl.current}\n onClose={() => setOpenEmojiPicker(false)}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'right',\n }}\n transformOrigin={{\n vertical: 'top',\n horizontal: 'right',\n }}\n >\n <Picker onSelect={onSelect} theme=\"dark\" />\n </Popover>\n </>\n );\n}\n\nEmojiIconButton.propTypes = {\n handleSelectEmoji: PropTypes.func.isRequired,\n emojiIconClassName: PropTypes.string,\n disableRipple: PropTypes.bool,\n closeOnSelect: PropTypes.bool,\n 'data-testid': PropTypes.string,\n tooltipProps: PropTypes.shape({}),\n icon: PropTypes.node,\n};\n\nexport default memo(EmojiIconButton);\n"],"names":["defaultTooltipProps","title","EmojiIconButton","_ref","handleSelectEmoji","_ref$emojiIconClassNa","emojiIconClassName","undefined","_ref$disableRipple","disableRipple","_ref$closeOnSelect","closeOnSelect","_ref$dataTestid","testId","_ref$tooltipProps","tooltipProps","_ref$icon","icon","useState","_useState2","_slicedToArray","_useState","openEmojiPicker","setOpenEmojiPicker","anchorEl","useRef","_jsxs","_Fragment","children","_jsx","IconButton","buttonRef","node","current","onClick","className","EmojiIcon","Popover","open","onClose","anchorOrigin","vertical","horizontal","transformOrigin","Picker","onSelect","emoji","theme","propTypes","PropTypes","func","isRequired","string","bool","shape","memo"],"mappings":"
|
|
1
|
+
{"version":3,"file":"EmojiIconButton.js","sources":["../../src/components/EmojiIconButton.js"],"sourcesContent":["import { memo, useRef, useState } from 'react';\nimport { Picker } from 'emoji-mart';\nimport PropTypes from 'prop-types';\nimport Popover from '@material-ui/core/Popover';\nimport Fade from '@material-ui/core/Fade';\n\nimport IconButton from '~components/IconButton';\nimport EmojiIcon from '~components/Icons/EmojiIcon';\n\nconst defaultTooltipProps = { title: 'Add Emoji' };\n\n/** @param {any} props Preserve the legacy component's permissive public prop type. */\nfunction EmojiIconButton({\n handleSelectEmoji,\n emojiIconClassName = undefined,\n disableRipple = false,\n closeOnSelect = true,\n 'data-testid': testId = 'generic_emojiButton',\n tooltipProps = defaultTooltipProps,\n icon = undefined,\n}) {\n const [openEmojiPicker, setOpenEmojiPicker] = useState(false);\n const anchorEl = useRef(null);\n\n const onSelect = emoji => {\n handleSelectEmoji(emoji);\n if (closeOnSelect) {\n setOpenEmojiPicker(false);\n }\n };\n\n return (\n <>\n <IconButton\n data-testid={testId}\n buttonRef={node => {\n anchorEl.current = node;\n }}\n aria-label=\"Emoji\"\n onClick={() => setOpenEmojiPicker(true)}\n disableRipple={disableRipple}\n className={emojiIconClassName}\n tooltipProps={tooltipProps}\n >\n {icon || <EmojiIcon />}\n </IconButton>\n\n <Popover\n open={openEmojiPicker}\n TransitionComponent={Fade}\n anchorEl={anchorEl.current}\n onClose={() => setOpenEmojiPicker(false)}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'right',\n }}\n transformOrigin={{\n vertical: 'top',\n horizontal: 'right',\n }}\n >\n <Picker onSelect={onSelect} theme=\"dark\" />\n </Popover>\n </>\n );\n}\n\nEmojiIconButton.propTypes = {\n handleSelectEmoji: PropTypes.func.isRequired,\n emojiIconClassName: PropTypes.string,\n disableRipple: PropTypes.bool,\n closeOnSelect: PropTypes.bool,\n 'data-testid': PropTypes.string,\n tooltipProps: PropTypes.shape({}),\n icon: PropTypes.node,\n};\n\nexport default memo(EmojiIconButton);\n"],"names":["defaultTooltipProps","title","EmojiIconButton","_ref","handleSelectEmoji","_ref$emojiIconClassNa","emojiIconClassName","undefined","_ref$disableRipple","disableRipple","_ref$closeOnSelect","closeOnSelect","_ref$dataTestid","testId","_ref$tooltipProps","tooltipProps","_ref$icon","icon","useState","_useState2","_slicedToArray","_useState","openEmojiPicker","setOpenEmojiPicker","anchorEl","useRef","_jsxs","_Fragment","children","_jsx","IconButton","buttonRef","node","current","onClick","className","EmojiIcon","Popover","open","TransitionComponent","Fade","onClose","anchorOrigin","vertical","horizontal","transformOrigin","Picker","onSelect","emoji","theme","propTypes","PropTypes","func","isRequired","string","bool","shape","memo"],"mappings":"iYASA,IAAMA,EAAsB,CAAEC,MAAO,aAGrC,SAASC,EAQNC,GAAA,IAPDC,IAAAA,kBAAiBC,EAAAF,EACjBG,mBAAAA,kBAAqBC,EAASF,EAAAG,EAAAL,EAC9BM,cAAAA,cAAqBD,EAAAE,EAAAP,EACrBQ,cAAAA,cAAoBD,EAAAE,EAAAT,EACpB,eAAeU,aAAS,sBAAqBD,EAAAE,EAAAX,EAC7CY,aAAAA,aAAef,EAAmBc,EAAAE,EAAAb,EAClCc,KAAAA,kBAAOV,EAASS,EAE8BE,EAAAA,GAAS,GAAMC,EAAAC,EAAAC,EAAA,GAAtDC,EAAeH,EAAA,GAAEI,EAAkBJ,EAAA,GACpCK,EAAWC,EAAO,MASxB,OACEC,EAAAC,EAAA,CAAAC,SAAA,CACEC,EAACC,EAAU,CACT,cAAajB,EACbkB,UAAW,SAAAC,GACTR,EAASS,QAAUD,CACnB,EACF,aAAW,QACXE,QAAS,WAAA,OAAMX,GAAmB,EAAM,EACxCd,cAAeA,EACf0B,UAAW7B,EACXS,aAAcA,EAAaa,SAE1BX,GAAQY,EAACO,EAAS,CAAA,KAGrBP,EAACQ,EAAO,CACNC,KAAMhB,EACNiB,oBAAqBC,EACrBhB,SAAUA,EAASS,QACnBQ,QAAS,WAAA,OAAMlB,GAAmB,EAAO,EACzCmB,aAAc,CACZC,SAAU,SACVC,WAAY,SAEdC,gBAAiB,CACfF,SAAU,MACVC,WAAY,SACZhB,SAEFC,EAACiB,EAAM,CAACC,SArCG,SAAAC,GACf5C,EAAkB4C,GACdrC,GACFY,GAAmB,IAkCW0B,MAAM,aAI1C,CAEA/C,EAAgBgD,UAAY,CAC1B9C,kBAAmB+C,EAAUC,KAAKC,WAClC/C,mBAAoB6C,EAAUG,OAC9B7C,cAAe0C,EAAUI,KACzB5C,cAAewC,EAAUI,KACzB,cAAeJ,EAAUG,OACzBvC,aAAcoC,EAAUK,MAAM,IAC9BvC,KAAMkC,EAAUnB,MAGlB,IAAeyB,EAAAA,EAAKvD"}
|
package/mcp-server/server.mjs
CHANGED
|
@@ -11,9 +11,10 @@ import { randomUUID } from 'crypto';
|
|
|
11
11
|
import { defaultResource, resourceFromAttributes } from '@opentelemetry/resources';
|
|
12
12
|
import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
|
|
13
13
|
import { readFile } from 'fs/promises';
|
|
14
|
-
import { join as join$1, resolve,
|
|
15
|
-
import { readFileSync } from 'fs';
|
|
14
|
+
import { join as join$1, dirname, resolve, sep } from 'path';
|
|
15
|
+
import { realpathSync, existsSync, statSync, readFileSync } from 'fs';
|
|
16
16
|
import { fileURLToPath } from 'url';
|
|
17
|
+
import { homedir } from 'os';
|
|
17
18
|
import { z } from 'zod';
|
|
18
19
|
|
|
19
20
|
const LOG_SYMBOLS = {
|
|
@@ -246,12 +247,23 @@ const validateDsn = dsn => {
|
|
|
246
247
|
return url.href;
|
|
247
248
|
};
|
|
248
249
|
|
|
249
|
-
const MCP_SERVER_VERSION = '1.
|
|
250
|
+
const MCP_SERVER_VERSION = '1.10.0';
|
|
250
251
|
|
|
251
|
-
var version = "3.80.0-
|
|
252
|
+
var version = "3.80.0-5";
|
|
252
253
|
|
|
253
254
|
const CORVA_UI_VERSION = version;
|
|
254
255
|
|
|
256
|
+
const getIdentityAttrs = identity => ({
|
|
257
|
+
...(identity?.appKey ? {
|
|
258
|
+
'corva.app.key': identity.appKey
|
|
259
|
+
} : {}),
|
|
260
|
+
...(identity?.packageName ? {
|
|
261
|
+
'corva.package.name': identity.packageName
|
|
262
|
+
} : {}),
|
|
263
|
+
...(identity?.repoName ? {
|
|
264
|
+
'corva.repo.name': identity.repoName
|
|
265
|
+
} : {})
|
|
266
|
+
});
|
|
255
267
|
const createMetricsClient = meter => {
|
|
256
268
|
const invocationCounter = meter.createCounter('mcp.server.tool.invocations', {
|
|
257
269
|
description: 'Number of tool invocations'
|
|
@@ -344,24 +356,14 @@ const createMetricsClient = meter => {
|
|
|
344
356
|
sessionCounter.add(1, {
|
|
345
357
|
'mcp.client.name': clientName || UNKNOWN_CLIENT_ATTR,
|
|
346
358
|
'mcp.client.version': clientVersion || UNKNOWN_CLIENT_ATTR,
|
|
347
|
-
...(projectIdentity
|
|
348
|
-
'corva.app.key': projectIdentity.appKey
|
|
349
|
-
} : {}),
|
|
350
|
-
...(projectIdentity?.packageName ? {
|
|
351
|
-
'corva.package.name': projectIdentity.packageName
|
|
352
|
-
} : {})
|
|
359
|
+
...getIdentityAttrs(projectIdentity)
|
|
353
360
|
});
|
|
354
361
|
},
|
|
355
362
|
recordSessionEnd: (durationMs, toolCount, clientName, clientVersion, projectIdentity) => {
|
|
356
363
|
const attrs = {
|
|
357
364
|
'mcp.client.name': clientName || UNKNOWN_CLIENT_ATTR,
|
|
358
365
|
'mcp.client.version': clientVersion || UNKNOWN_CLIENT_ATTR,
|
|
359
|
-
...(projectIdentity
|
|
360
|
-
'corva.app.key': projectIdentity.appKey
|
|
361
|
-
} : {}),
|
|
362
|
-
...(projectIdentity?.packageName ? {
|
|
363
|
-
'corva.package.name': projectIdentity.packageName
|
|
364
|
-
} : {})
|
|
366
|
+
...getIdentityAttrs(projectIdentity)
|
|
365
367
|
};
|
|
366
368
|
sessionDuration.record(durationMs, attrs);
|
|
367
369
|
sessionToolCount.record(toolCount, attrs);
|
|
@@ -530,6 +532,9 @@ const recordInitSpan = (tracer, attrs) => {
|
|
|
530
532
|
if (attrs.packageName) {
|
|
531
533
|
span.setAttribute('corva.package.name', attrs.packageName);
|
|
532
534
|
}
|
|
535
|
+
if (attrs.repoName) {
|
|
536
|
+
span.setAttribute('corva.repo.name', attrs.repoName);
|
|
537
|
+
}
|
|
533
538
|
} finally {
|
|
534
539
|
span.end();
|
|
535
540
|
}
|
|
@@ -937,6 +942,131 @@ const extractContextFromMeta = meta => {
|
|
|
937
942
|
return propagation.extract(context.active(), meta, metaGetter);
|
|
938
943
|
};
|
|
939
944
|
|
|
945
|
+
const URL_WITH_SCHEME = /^[a-z][a-z0-9+.-]*:\/\//i;
|
|
946
|
+
// A drive letter and a colon is a local Windows path, as in git's `has_dos_drive_prefix`. Read as
|
|
947
|
+
// scp-like, `C:\Users\alice\repo` would export the path with the username.
|
|
948
|
+
const LOCAL_PREFIX = /^(?:file:|[a-z]:)/i;
|
|
949
|
+
// Git's scp-like form, `[user@]host:path`, where the host may be a bracketed IPv6 address. A slash
|
|
950
|
+
// before the first colon means a local path, so neither the user nor the host may contain one.
|
|
951
|
+
const SCP_LIKE = /^(?:[^@/:]+@)?(?:\[[^\]/]*\]|[^:/[\]]+):(.+)$/;
|
|
952
|
+
|
|
953
|
+
/**
|
|
954
|
+
* Returns the last path segment of a git remote URL without `.git`, or null for a local path
|
|
955
|
+
* (including a Windows drive path), a `file:` URL, a URL without a path and a URL it cannot parse.
|
|
956
|
+
* Only the repository name leaves the machine: never the host, owner, user or credentials.
|
|
957
|
+
*/
|
|
958
|
+
const getRepoNameFromUrl = url => {
|
|
959
|
+
if (LOCAL_PREFIX.test(url)) {
|
|
960
|
+
return null;
|
|
961
|
+
}
|
|
962
|
+
let path;
|
|
963
|
+
if (URL_WITH_SCHEME.test(url)) {
|
|
964
|
+
try {
|
|
965
|
+
path = new URL(url).pathname;
|
|
966
|
+
} catch {
|
|
967
|
+
return null;
|
|
968
|
+
}
|
|
969
|
+
} else {
|
|
970
|
+
// The query goes first: an `@` or `:` inside it must not be read as the user or the host.
|
|
971
|
+
path = SCP_LIKE.exec(url.split(/[?#]/)[0])?.[1];
|
|
972
|
+
}
|
|
973
|
+
const name = path?.split('/').filter(Boolean).pop()?.replace(/\.git$/, '');
|
|
974
|
+
return name || null;
|
|
975
|
+
};
|
|
976
|
+
|
|
977
|
+
const SECTION_HEADER = /^\[\s*([^\s\]"]+)(?:\s+"((?:[^"\\]|\\.)*)")?\s*\]/;
|
|
978
|
+
const URL_ENTRY = /^url\s*=\s*(.*)$/i;
|
|
979
|
+
|
|
980
|
+
// A `.git` in the home directory or above it belongs to a dotfiles or system repository, not to
|
|
981
|
+
// the project. Real paths, so a symbolic link cannot walk past the stop.
|
|
982
|
+
const findGitEntry = (startDir, homeDir) => {
|
|
983
|
+
const home = realpathSync(homeDir);
|
|
984
|
+
const isHomeOrAbove = dir => dir === home || home.startsWith(`${dir}${sep}`);
|
|
985
|
+
for (let dir = realpathSync(startDir); !isHomeOrAbove(dir) && dirname(dir) !== dir; dir = dirname(dir)) {
|
|
986
|
+
const entry = join$1(dir, '.git');
|
|
987
|
+
if (existsSync(entry)) {
|
|
988
|
+
return entry;
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
return null;
|
|
992
|
+
};
|
|
993
|
+
|
|
994
|
+
// A linked worktree or a submodule has a `.git` file that points to its git directory; a worktree's
|
|
995
|
+
// git directory points on to the shared one through `commondir`, and that is where `origin` lives.
|
|
996
|
+
const getConfigPath = gitEntry => {
|
|
997
|
+
if (statSync(gitEntry).isDirectory()) {
|
|
998
|
+
return join$1(gitEntry, 'config');
|
|
999
|
+
}
|
|
1000
|
+
const gitDirPath = /^gitdir:\s*(.+)$/m.exec(readFileSync(gitEntry, 'utf-8'))?.[1].trim();
|
|
1001
|
+
if (!gitDirPath) {
|
|
1002
|
+
return null;
|
|
1003
|
+
}
|
|
1004
|
+
const gitDir = resolve(dirname(gitEntry), gitDirPath);
|
|
1005
|
+
const commonDirFile = join$1(gitDir, 'commondir');
|
|
1006
|
+
const commonDir = existsSync(commonDirFile) ? resolve(gitDir, readFileSync(commonDirFile, 'utf-8').trim()) : gitDir;
|
|
1007
|
+
return join$1(commonDir, 'config');
|
|
1008
|
+
};
|
|
1009
|
+
|
|
1010
|
+
// A git config value can mix quoted and unquoted parts, and an unquoted `#` or `;` starts a comment
|
|
1011
|
+
// anywhere in it. Reading only a leading quoted part, or only a comment after whitespace, would
|
|
1012
|
+
// return the owner or a commented-out URL.
|
|
1013
|
+
const parseValue = raw => {
|
|
1014
|
+
let value = '';
|
|
1015
|
+
let quoted = false;
|
|
1016
|
+
for (let i = 0; i < raw.length; i += 1) {
|
|
1017
|
+
const char = raw[i];
|
|
1018
|
+
if (char === '\\') {
|
|
1019
|
+
value += raw[i + 1] ?? '';
|
|
1020
|
+
i += 1;
|
|
1021
|
+
} else if (char === '"') {
|
|
1022
|
+
quoted = !quoted;
|
|
1023
|
+
} else if (!quoted && (char === '#' || char === ';')) {
|
|
1024
|
+
break;
|
|
1025
|
+
} else {
|
|
1026
|
+
value += char;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
return value.trim();
|
|
1030
|
+
};
|
|
1031
|
+
|
|
1032
|
+
// `include`/`includeIf` are not followed: they can point anywhere on the machine. The first `url`
|
|
1033
|
+
// wins because that is the one `git fetch` uses.
|
|
1034
|
+
const readOriginUrl = configPath => {
|
|
1035
|
+
let inOrigin = false;
|
|
1036
|
+
for (const rawLine of readFileSync(configPath, 'utf-8').split(/\r?\n/)) {
|
|
1037
|
+
let line = rawLine.trim();
|
|
1038
|
+
const section = SECTION_HEADER.exec(line);
|
|
1039
|
+
|
|
1040
|
+
// Git also accepts an entry on the header line: `[remote "origin"] url = ...`.
|
|
1041
|
+
if (section) {
|
|
1042
|
+
inOrigin = section[1].toLowerCase() === 'remote' && section[2] === 'origin';
|
|
1043
|
+
line = line.slice(section[0].length).trim();
|
|
1044
|
+
}
|
|
1045
|
+
const value = inOrigin ? URL_ENTRY.exec(line)?.[1] : undefined;
|
|
1046
|
+
if (value !== undefined) {
|
|
1047
|
+
return parseValue(value);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
return null;
|
|
1051
|
+
};
|
|
1052
|
+
|
|
1053
|
+
/**
|
|
1054
|
+
* Returns the repository name of the `origin` remote of the nearest git repository above
|
|
1055
|
+
* `startDir`, or null. Reads the git files directly instead of spawning `git`, which may be missing
|
|
1056
|
+
* and would cost a process on every session start. Never throws.
|
|
1057
|
+
*/
|
|
1058
|
+
const resolveRepoName = (startDir, homeDir) => {
|
|
1059
|
+
try {
|
|
1060
|
+
// `homedir()` throws when HOME is unset and the user has no passwd entry, as in some containers.
|
|
1061
|
+
const gitEntry = findGitEntry(startDir, homeDir ?? homedir());
|
|
1062
|
+
const configPath = gitEntry && getConfigPath(gitEntry);
|
|
1063
|
+
const url = configPath && readOriginUrl(configPath);
|
|
1064
|
+
return url ? getRepoNameFromUrl(url) : null;
|
|
1065
|
+
} catch {
|
|
1066
|
+
return null;
|
|
1067
|
+
}
|
|
1068
|
+
};
|
|
1069
|
+
|
|
940
1070
|
const readJsonField = (filePath, ...keys) => {
|
|
941
1071
|
try {
|
|
942
1072
|
let value = JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
@@ -974,12 +1104,16 @@ const getProjectIdentityAttrs = identity => {
|
|
|
974
1104
|
if (identity?.packageName) {
|
|
975
1105
|
attrs['corva.package.name'] = identity.packageName;
|
|
976
1106
|
}
|
|
1107
|
+
if (identity?.repoName) {
|
|
1108
|
+
attrs['corva.repo.name'] = identity.repoName;
|
|
1109
|
+
}
|
|
977
1110
|
return attrs;
|
|
978
1111
|
};
|
|
979
1112
|
const resolveProjectIdentity = async (server, logger) => {
|
|
980
1113
|
const empty = {
|
|
981
1114
|
appKey: null,
|
|
982
|
-
packageName: null
|
|
1115
|
+
packageName: null,
|
|
1116
|
+
repoName: null
|
|
983
1117
|
};
|
|
984
1118
|
try {
|
|
985
1119
|
const capabilities = server.getClientCapabilities();
|
|
@@ -995,15 +1129,20 @@ const resolveProjectIdentity = async (server, logger) => {
|
|
|
995
1129
|
const rootPath = fileURLToPath(roots[0].uri);
|
|
996
1130
|
const appKey = findUpJsonField(rootPath, 'manifest.json', 'application', 'key');
|
|
997
1131
|
const packageName = findUpJsonField(rootPath, 'package.json', 'name');
|
|
1132
|
+
const repoName = resolveRepoName(rootPath);
|
|
998
1133
|
if (appKey) {
|
|
999
1134
|
logger.info(`Consuming app: ${appKey}`);
|
|
1000
1135
|
}
|
|
1001
1136
|
if (packageName) {
|
|
1002
1137
|
logger.info(`Consuming package: ${packageName}`);
|
|
1003
1138
|
}
|
|
1139
|
+
if (repoName) {
|
|
1140
|
+
logger.info(`Consuming repository: ${repoName}`);
|
|
1141
|
+
}
|
|
1004
1142
|
return {
|
|
1005
1143
|
appKey,
|
|
1006
|
-
packageName
|
|
1144
|
+
packageName,
|
|
1145
|
+
repoName
|
|
1007
1146
|
};
|
|
1008
1147
|
} catch {
|
|
1009
1148
|
return empty;
|
|
@@ -1077,7 +1216,8 @@ const recordSessionStart = async ({
|
|
|
1077
1216
|
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
1078
1217
|
networkTransport: MCP_NETWORK_TRANSPORT,
|
|
1079
1218
|
appKey: projectIdentity?.appKey ?? undefined,
|
|
1080
|
-
packageName: projectIdentity?.packageName ?? undefined
|
|
1219
|
+
packageName: projectIdentity?.packageName ?? undefined,
|
|
1220
|
+
repoName: projectIdentity?.repoName ?? undefined
|
|
1081
1221
|
});
|
|
1082
1222
|
};
|
|
1083
1223
|
|
|
@@ -22670,7 +22810,7 @@ const diagnosticsToolName = 'get_diagnostics';
|
|
|
22670
22810
|
const diagnosticsToolTitle = 'Get Server Diagnostics';
|
|
22671
22811
|
const diagnosticsToolDescription = `Get MCP server health metrics.
|
|
22672
22812
|
Returns server version, uptime, memory usage, request statistics, telemetry status,
|
|
22673
|
-
whether feedback can reach the maintainers, project identity (app key and
|
|
22813
|
+
whether feedback can reach the maintainers, project identity (app key, package name and repository name), and the prompts this server registers.`;
|
|
22674
22814
|
const diagnosticsToolSchema = {};
|
|
22675
22815
|
const formatUptime = ms => {
|
|
22676
22816
|
const seconds = Math.floor(ms / 1000);
|
|
@@ -22738,6 +22878,7 @@ const handleGetDiagnostics = (stats, telemetry, identity, registeredPromptNames)
|
|
|
22738
22878
|
text += h2('Project Identity');
|
|
22739
22879
|
text += `${bold('App key')}: ${identity?.appKey ?? 'N/A'}\n`;
|
|
22740
22880
|
text += `${bold('Package name')}: ${identity?.packageName ?? 'N/A'}\n`;
|
|
22881
|
+
text += `${bold('Repository')}: ${identity?.repoName ?? 'N/A'}\n`;
|
|
22741
22882
|
if (registeredPromptNames?.length) {
|
|
22742
22883
|
text += `\n${h2('Registered Prompts')}`;
|
|
22743
22884
|
text += `${list(registeredPromptNames.map(name => `\`${name}\``))}\n\n`;
|