@firfi/huly-mcp 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.cjs +248 -86
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -351,8 +351,8 @@ Resource roadmap:
|
|
|
351
351
|
| `delete_teamspace` | Permanently delete a Huly document teamspace. This action cannot be undone. |
|
|
352
352
|
| `list_documents` | List documents in a Huly teamspace. Returns documents sorted by modification date (newest first). Each result includes a 'url' field pointing to the document in the Huly web app. Supports searching by title substring (titleSearch) and content (contentSearch). |
|
|
353
353
|
| `get_document` | Retrieve full details for a Huly document including markdown content and a 'url' field pointing to the document in the Huly web app. Use this to view document content and metadata. |
|
|
354
|
-
| `create_document` | Create a new document in a Huly teamspace. Content
|
|
355
|
-
| `edit_document` | Edit an existing Huly document.
|
|
354
|
+
| `create_document` | Create a new document in a Huly teamspace. Content is markdown and supports native Mermaid diagrams (```mermaid blocks render interactively in Huly UI). Use markdown links to current-workspace Huly browse URLs for native references; Huly browse links returned in get_document content round-trip as native references. The URL identifies the object; link text is display text; plain issue keys stay text. External URLs stay normal markdown links. Optionally pass parent as a document title or ID to create a nested child document; invalid parents fail instead of silently creating a top-level document. Returns the created document id and a 'url' field pointing to the document in the Huly web app. Use link_document_to_issue only if you also want an issue-document association. |
|
|
355
|
+
| `edit_document` | Edit an existing Huly document. You may rename with title and/or edit the body. Body editing has two mutually exclusive modes: (1) content replaces the entire markdown body, (2) old_text + new_text performs exact targeted search-and-replace. Use markdown links to current-workspace Huly browse URLs for native references; Huly browse links returned in get_document content round-trip as native references. The URL identifies the object; link text is display text; plain issue keys stay text. External URLs stay normal markdown links. For targeted replace, multiple matches error unless replace_all is true; empty new_text deletes matched text. Content supports native Mermaid diagrams. Returns a 'url' field pointing to the document in the Huly web app. |
|
|
356
356
|
| `list_inline_comments` | List inline comment threads from a Huly document. Extracts comments embedded in document content as ProseMirror marks. Each comment includes the highlighted text and thread ID. Set includeReplies=true to also fetch thread reply messages with sender names. |
|
|
357
357
|
| `delete_document` | Permanently delete a Huly document. This action cannot be undone. |
|
|
358
358
|
|
package/dist/index.cjs
CHANGED
|
@@ -62706,41 +62706,41 @@ var require_model = __commonJS({
|
|
|
62706
62706
|
var model_exports = {};
|
|
62707
62707
|
__export2(model_exports, {
|
|
62708
62708
|
MarkupMarkType: () => MarkupMarkType,
|
|
62709
|
-
MarkupNodeType: () =>
|
|
62709
|
+
MarkupNodeType: () => MarkupNodeType2,
|
|
62710
62710
|
emptyMarkupNode: () => emptyMarkupNode
|
|
62711
62711
|
});
|
|
62712
62712
|
module2.exports = __toCommonJS2(model_exports);
|
|
62713
|
-
var
|
|
62714
|
-
|
|
62715
|
-
|
|
62716
|
-
|
|
62717
|
-
|
|
62718
|
-
|
|
62719
|
-
|
|
62720
|
-
|
|
62721
|
-
|
|
62722
|
-
|
|
62723
|
-
|
|
62724
|
-
|
|
62725
|
-
|
|
62726
|
-
|
|
62727
|
-
|
|
62728
|
-
|
|
62729
|
-
|
|
62730
|
-
|
|
62731
|
-
|
|
62732
|
-
|
|
62733
|
-
|
|
62734
|
-
|
|
62735
|
-
|
|
62736
|
-
|
|
62737
|
-
|
|
62738
|
-
|
|
62739
|
-
|
|
62740
|
-
|
|
62741
|
-
|
|
62742
|
-
return
|
|
62743
|
-
})(
|
|
62713
|
+
var MarkupNodeType2 = /* @__PURE__ */ ((MarkupNodeType22) => {
|
|
62714
|
+
MarkupNodeType22["doc"] = "doc";
|
|
62715
|
+
MarkupNodeType22["paragraph"] = "paragraph";
|
|
62716
|
+
MarkupNodeType22["blockquote"] = "blockquote";
|
|
62717
|
+
MarkupNodeType22["horizontal_rule"] = "horizontalRule";
|
|
62718
|
+
MarkupNodeType22["heading"] = "heading";
|
|
62719
|
+
MarkupNodeType22["code_block"] = "codeBlock";
|
|
62720
|
+
MarkupNodeType22["text"] = "text";
|
|
62721
|
+
MarkupNodeType22["image"] = "image";
|
|
62722
|
+
MarkupNodeType22["file"] = "file";
|
|
62723
|
+
MarkupNodeType22["reference"] = "reference";
|
|
62724
|
+
MarkupNodeType22["emoji"] = "emoji";
|
|
62725
|
+
MarkupNodeType22["hard_break"] = "hardBreak";
|
|
62726
|
+
MarkupNodeType22["ordered_list"] = "orderedList";
|
|
62727
|
+
MarkupNodeType22["bullet_list"] = "bulletList";
|
|
62728
|
+
MarkupNodeType22["list_item"] = "listItem";
|
|
62729
|
+
MarkupNodeType22["taskList"] = "taskList";
|
|
62730
|
+
MarkupNodeType22["taskItem"] = "taskItem";
|
|
62731
|
+
MarkupNodeType22["todoList"] = "todoList";
|
|
62732
|
+
MarkupNodeType22["todoItem"] = "todoItem";
|
|
62733
|
+
MarkupNodeType22["subLink"] = "subLink";
|
|
62734
|
+
MarkupNodeType22["table"] = "table";
|
|
62735
|
+
MarkupNodeType22["table_row"] = "tableRow";
|
|
62736
|
+
MarkupNodeType22["table_cell"] = "tableCell";
|
|
62737
|
+
MarkupNodeType22["table_header"] = "tableHeader";
|
|
62738
|
+
MarkupNodeType22["mermaid"] = "mermaid";
|
|
62739
|
+
MarkupNodeType22["comment"] = "comment";
|
|
62740
|
+
MarkupNodeType22["markdown"] = "markdown";
|
|
62741
|
+
MarkupNodeType22["embed"] = "embed";
|
|
62742
|
+
return MarkupNodeType22;
|
|
62743
|
+
})(MarkupNodeType2 || {});
|
|
62744
62744
|
var MarkupMarkType = /* @__PURE__ */ ((MarkupMarkType2) => {
|
|
62745
62745
|
MarkupMarkType2["link"] = "link";
|
|
62746
62746
|
MarkupMarkType2["em"] = "italic";
|
|
@@ -81771,7 +81771,7 @@ var require_connection2 = __commonJS({
|
|
|
81771
81771
|
});
|
|
81772
81772
|
module2.exports = __toCommonJS2(connection_exports);
|
|
81773
81773
|
var import_analytics = require_lib2();
|
|
81774
|
-
var
|
|
81774
|
+
var import_client39 = __toESM2(require_lib6());
|
|
81775
81775
|
var import_core57 = __toESM2(require_lib4());
|
|
81776
81776
|
var import_platform4 = __toESM2(require_lib());
|
|
81777
81777
|
var import_rpc = require_lib18();
|
|
@@ -81882,7 +81882,7 @@ var require_connection2 = __commonJS({
|
|
|
81882
81882
|
}
|
|
81883
81883
|
if (!this.closed) {
|
|
81884
81884
|
void this.sendRequest({
|
|
81885
|
-
method:
|
|
81885
|
+
method: import_client39.pingConst,
|
|
81886
81886
|
params: [],
|
|
81887
81887
|
once: true,
|
|
81888
81888
|
handleResult: /* @__PURE__ */ __name(async (result) => {
|
|
@@ -81915,7 +81915,7 @@ var require_connection2 = __commonJS({
|
|
|
81915
81915
|
}
|
|
81916
81916
|
}
|
|
81917
81917
|
isConnected() {
|
|
81918
|
-
return this.websocket != null && this.websocket.readyState ===
|
|
81918
|
+
return this.websocket != null && this.websocket.readyState === import_client39.ClientSocketReadyState.OPEN && this.helloReceived;
|
|
81919
81919
|
}
|
|
81920
81920
|
delay = 0;
|
|
81921
81921
|
onConnectHandlers = [];
|
|
@@ -82055,8 +82055,8 @@ var require_connection2 = __commonJS({
|
|
|
82055
82055
|
}
|
|
82056
82056
|
return;
|
|
82057
82057
|
}
|
|
82058
|
-
if (resp.result ===
|
|
82059
|
-
void this.sendRequest({ method:
|
|
82058
|
+
if (resp.result === import_client39.pingConst) {
|
|
82059
|
+
void this.sendRequest({ method: import_client39.pingConst, params: [] }).catch((err) => {
|
|
82060
82060
|
this.ctx.error("failed to send ping", { err });
|
|
82061
82061
|
});
|
|
82062
82062
|
return;
|
|
@@ -82148,15 +82148,15 @@ var require_connection2 = __commonJS({
|
|
|
82148
82148
|
}
|
|
82149
82149
|
}
|
|
82150
82150
|
checkArrayBufferPing(data) {
|
|
82151
|
-
if (data.byteLength ===
|
|
82151
|
+
if (data.byteLength === import_client39.pingConst.length || data.byteLength === import_client39.pongConst.length) {
|
|
82152
82152
|
const text = new TextDecoder().decode(data);
|
|
82153
|
-
if (text ===
|
|
82154
|
-
void this.sendRequest({ method:
|
|
82153
|
+
if (text === import_client39.pingConst) {
|
|
82154
|
+
void this.sendRequest({ method: import_client39.pingConst, params: [] }).catch((err) => {
|
|
82155
82155
|
this.ctx.error("failed to send ping", { err });
|
|
82156
82156
|
});
|
|
82157
82157
|
return true;
|
|
82158
82158
|
}
|
|
82159
|
-
if (text ===
|
|
82159
|
+
if (text === import_client39.pongConst) {
|
|
82160
82160
|
this.pingResponse = Date.now();
|
|
82161
82161
|
return true;
|
|
82162
82162
|
}
|
|
@@ -82166,7 +82166,7 @@ var require_connection2 = __commonJS({
|
|
|
82166
82166
|
openConnection(ctx, socketId) {
|
|
82167
82167
|
this.binaryMode = false;
|
|
82168
82168
|
this.helloReceived = false;
|
|
82169
|
-
const clientSocketFactory = this.opt?.socketFactory ?? (0, import_platform4.getMetadata)(
|
|
82169
|
+
const clientSocketFactory = this.opt?.socketFactory ?? (0, import_platform4.getMetadata)(import_client39.default.metadata.ClientSocketFactory) ?? ((url4) => {
|
|
82170
82170
|
const s = new WebSocket(url4);
|
|
82171
82171
|
return s;
|
|
82172
82172
|
});
|
|
@@ -82201,12 +82201,12 @@ var require_connection2 = __commonJS({
|
|
|
82201
82201
|
if (this.websocket !== wsocket) {
|
|
82202
82202
|
return;
|
|
82203
82203
|
}
|
|
82204
|
-
if (event.data ===
|
|
82204
|
+
if (event.data === import_client39.pongConst) {
|
|
82205
82205
|
this.pingResponse = Date.now();
|
|
82206
82206
|
return;
|
|
82207
82207
|
}
|
|
82208
|
-
if (event.data ===
|
|
82209
|
-
void this.sendRequest({ method:
|
|
82208
|
+
if (event.data === import_client39.pingConst) {
|
|
82209
|
+
void this.sendRequest({ method: import_client39.pingConst, params: [] }).catch((err) => {
|
|
82210
82210
|
this.ctx.error("failed to send ping", { err });
|
|
82211
82211
|
});
|
|
82212
82212
|
return;
|
|
@@ -82271,8 +82271,8 @@ var require_connection2 = __commonJS({
|
|
|
82271
82271
|
if (this.websocket !== wsocket) {
|
|
82272
82272
|
return;
|
|
82273
82273
|
}
|
|
82274
|
-
const useBinary = this.opt?.useBinaryProtocol ?? (0, import_platform4.getMetadata)(
|
|
82275
|
-
this.compressionMode = this.opt?.useProtocolCompression ?? (0, import_platform4.getMetadata)(
|
|
82274
|
+
const useBinary = this.opt?.useBinaryProtocol ?? (0, import_platform4.getMetadata)(import_client39.default.metadata.UseBinaryProtocol) ?? true;
|
|
82275
|
+
this.compressionMode = this.opt?.useProtocolCompression ?? (0, import_platform4.getMetadata)(import_client39.default.metadata.UseProtocolCompression) ?? false;
|
|
82276
82276
|
const helloRequest = {
|
|
82277
82277
|
method: "hello",
|
|
82278
82278
|
params: [],
|
|
@@ -82318,13 +82318,13 @@ var require_connection2 = __commonJS({
|
|
|
82318
82318
|
if (w instanceof Promise) {
|
|
82319
82319
|
await w;
|
|
82320
82320
|
}
|
|
82321
|
-
if (data.method !==
|
|
82321
|
+
if (data.method !== import_client39.pingConst) {
|
|
82322
82322
|
this.requests.set(id, promise4);
|
|
82323
82323
|
}
|
|
82324
82324
|
promise4.sendData = () => {
|
|
82325
|
-
if (this.websocket?.readyState ===
|
|
82325
|
+
if (this.websocket?.readyState === import_client39.ClientSocketReadyState.OPEN) {
|
|
82326
82326
|
promise4.startTime = Date.now();
|
|
82327
|
-
if (data.method !==
|
|
82327
|
+
if (data.method !== import_client39.pingConst) {
|
|
82328
82328
|
const dta = this.rpcHandler.serialize(
|
|
82329
82329
|
{
|
|
82330
82330
|
method: data.method,
|
|
@@ -82337,7 +82337,7 @@ var require_connection2 = __commonJS({
|
|
|
82337
82337
|
);
|
|
82338
82338
|
this.websocket?.send(dta);
|
|
82339
82339
|
} else {
|
|
82340
|
-
this.websocket?.send(
|
|
82340
|
+
this.websocket?.send(import_client39.pingConst);
|
|
82341
82341
|
}
|
|
82342
82342
|
}
|
|
82343
82343
|
};
|
|
@@ -82351,7 +82351,7 @@ var require_connection2 = __commonJS({
|
|
|
82351
82351
|
};
|
|
82352
82352
|
}
|
|
82353
82353
|
promise4.sendData();
|
|
82354
|
-
if (data.method !==
|
|
82354
|
+
if (data.method !== import_client39.pingConst) {
|
|
82355
82355
|
return await promise4.promise;
|
|
82356
82356
|
}
|
|
82357
82357
|
},
|
|
@@ -82517,7 +82517,7 @@ var require_lib19 = __commonJS({
|
|
|
82517
82517
|
default: () => index_default
|
|
82518
82518
|
});
|
|
82519
82519
|
module2.exports = __toCommonJS2(index_exports2);
|
|
82520
|
-
var
|
|
82520
|
+
var import_client39 = __toESM2(require_lib6());
|
|
82521
82521
|
var import_core57 = __toESM2(require_lib4());
|
|
82522
82522
|
var import_platform4 = __toESM2(require_lib());
|
|
82523
82523
|
var import_connection = require_connection2();
|
|
@@ -82561,8 +82561,8 @@ var require_lib19 = __commonJS({
|
|
|
82561
82561
|
return {
|
|
82562
82562
|
function: {
|
|
82563
82563
|
GetClient: /* @__PURE__ */ __name(async (token, endpoint, opt) => {
|
|
82564
|
-
const filterModel = (0, import_platform4.getMetadata)(
|
|
82565
|
-
const extraFilter = (0, import_platform4.getMetadata)(
|
|
82564
|
+
const filterModel = (0, import_platform4.getMetadata)(import_client39.default.metadata.FilterModel) ?? "none";
|
|
82565
|
+
const extraFilter = (0, import_platform4.getMetadata)(import_client39.default.metadata.ExtraFilter) ?? [];
|
|
82566
82566
|
const handler = /* @__PURE__ */ __name(async (handler2) => {
|
|
82567
82567
|
const url4 = (0, import_core57.concatLink)(endpoint, `/${token}`);
|
|
82568
82568
|
const upgradeHandler = /* @__PURE__ */ __name((...txes) => {
|
|
@@ -82590,7 +82590,7 @@ var require_lib19 = __commonJS({
|
|
|
82590
82590
|
throw new Error("Workspace or account not found in token");
|
|
82591
82591
|
}
|
|
82592
82592
|
const newOpt = { ...opt };
|
|
82593
|
-
const connectTimeout = opt?.connectionTimeout ?? (0, import_platform4.getMetadata)(
|
|
82593
|
+
const connectTimeout = opt?.connectionTimeout ?? (0, import_platform4.getMetadata)(import_client39.default.metadata.ConnectionTimeout);
|
|
82594
82594
|
let connectPromise;
|
|
82595
82595
|
if ((connectTimeout ?? 0) > 0) {
|
|
82596
82596
|
connectPromise = new Promise((resolve2, reject) => {
|
|
@@ -82642,7 +82642,7 @@ var require_lib19 = __commonJS({
|
|
|
82642
82642
|
function returnUITxes(txes, extraFilter) {
|
|
82643
82643
|
const configs = /* @__PURE__ */ new Map();
|
|
82644
82644
|
(0, import_core57.fillConfiguration)(txes, configs);
|
|
82645
|
-
const allowedPlugins = [...(0, import_platform4.getPlugins)(), ...(0, import_platform4.getMetadata)(
|
|
82645
|
+
const allowedPlugins = [...(0, import_platform4.getPlugins)(), ...(0, import_platform4.getMetadata)(import_client39.default.metadata.ExtraPlugins) ?? []];
|
|
82646
82646
|
const excludedPlugins = Array.from(configs.values()).filter(
|
|
82647
82647
|
(it) => !it.enabled || !allowedPlugins.includes(it.pluginId) || extraFilter.includes(it.pluginId)
|
|
82648
82648
|
);
|
|
@@ -82690,7 +82690,7 @@ var require_lib19 = __commonJS({
|
|
|
82690
82690
|
}
|
|
82691
82691
|
__name(returnClientTxes, "returnClientTxes");
|
|
82692
82692
|
function createModelPersistence(workspace) {
|
|
82693
|
-
const overrideStore = (0, import_platform4.getMetadata)(
|
|
82693
|
+
const overrideStore = (0, import_platform4.getMetadata)(import_client39.default.metadata.OverridePersistenceStore);
|
|
82694
82694
|
if (overrideStore !== void 0) {
|
|
82695
82695
|
return overrideStore;
|
|
82696
82696
|
}
|
|
@@ -82787,11 +82787,11 @@ var require_client6 = __commonJS({
|
|
|
82787
82787
|
});
|
|
82788
82788
|
module2.exports = __toCommonJS2(client_exports);
|
|
82789
82789
|
var import_account_client2 = require_lib5();
|
|
82790
|
-
var
|
|
82790
|
+
var import_client39 = __toESM2(require_lib6());
|
|
82791
82791
|
var import_core57 = require_lib4();
|
|
82792
82792
|
var import_platform4 = require_lib();
|
|
82793
82793
|
var import_config9 = require_config();
|
|
82794
|
-
var
|
|
82794
|
+
var import_markup12 = require_markup();
|
|
82795
82795
|
var import_utils14 = require_utils9();
|
|
82796
82796
|
async function connect(url4, options) {
|
|
82797
82797
|
const config3 = await (0, import_config9.loadServerConfig)(url4);
|
|
@@ -82813,9 +82813,9 @@ var require_client6 = __commonJS({
|
|
|
82813
82813
|
}
|
|
82814
82814
|
__name(connect, "connect");
|
|
82815
82815
|
async function createClient(url4, endpoint, token, workspaceUuid, account, config3, options) {
|
|
82816
|
-
(0, import_platform4.addLocation)(
|
|
82816
|
+
(0, import_platform4.addLocation)(import_client39.clientId, () => Promise.resolve().then(() => __toESM(require_lib19())));
|
|
82817
82817
|
const { socketFactory, connectionTimeout } = options;
|
|
82818
|
-
const clientFactory = await (0, import_platform4.getResource)(
|
|
82818
|
+
const clientFactory = await (0, import_platform4.getResource)(import_client39.default.function.GetClient);
|
|
82819
82819
|
const connection = await clientFactory(token, endpoint, {
|
|
82820
82820
|
socketFactory,
|
|
82821
82821
|
connectionTimeout
|
|
@@ -82832,7 +82832,7 @@ var require_client6 = __commonJS({
|
|
|
82832
82832
|
this.connection = connection;
|
|
82833
82833
|
this.account = account;
|
|
82834
82834
|
this.client = new import_core57.TxOperations(connection, account.primarySocialId);
|
|
82835
|
-
this.markup = (0,
|
|
82835
|
+
this.markup = (0, import_markup12.createMarkupOperations)(url4, workspace, token, config3);
|
|
82836
82836
|
}
|
|
82837
82837
|
static {
|
|
82838
82838
|
__name(this, "PlatformClientImpl");
|
|
@@ -82861,7 +82861,7 @@ var require_client6 = __commonJS({
|
|
|
82861
82861
|
async processMarkup(_class, id, data) {
|
|
82862
82862
|
const result = {};
|
|
82863
82863
|
for (const [key, value3] of Object.entries(data)) {
|
|
82864
|
-
if (value3 instanceof
|
|
82864
|
+
if (value3 instanceof import_markup12.MarkupContent) {
|
|
82865
82865
|
result[key] = this.markup.uploadMarkup(_class, id, key, value3.content, value3.kind);
|
|
82866
82866
|
} else {
|
|
82867
82867
|
result[key] = value3;
|
|
@@ -83936,11 +83936,11 @@ var require_storage2 = __commonJS({
|
|
|
83936
83936
|
var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
|
|
83937
83937
|
var storage_exports = {};
|
|
83938
83938
|
__export2(storage_exports, {
|
|
83939
|
-
connectStorage: () =>
|
|
83940
|
-
createStorageClient: () =>
|
|
83939
|
+
connectStorage: () => import_client39.connectStorage,
|
|
83940
|
+
createStorageClient: () => import_client39.createStorageClient
|
|
83941
83941
|
});
|
|
83942
83942
|
module2.exports = __toCommonJS2(storage_exports);
|
|
83943
|
-
var
|
|
83943
|
+
var import_client39 = require_client7();
|
|
83944
83944
|
__reExport2(storage_exports, require_error3(), module2.exports);
|
|
83945
83945
|
__reExport2(storage_exports, require_types8(), module2.exports);
|
|
83946
83946
|
}
|
|
@@ -152358,6 +152358,16 @@ var DocumentEditModeError = class extends Schema_exports.TaggedError()(
|
|
|
152358
152358
|
return `Invalid edit_document mode: ${this.reason}`;
|
|
152359
152359
|
}
|
|
152360
152360
|
};
|
|
152361
|
+
var DocumentReferenceError = class extends Schema_exports.TaggedError()(
|
|
152362
|
+
"DocumentReferenceError",
|
|
152363
|
+
{
|
|
152364
|
+
reason: Schema_exports.String
|
|
152365
|
+
}
|
|
152366
|
+
) {
|
|
152367
|
+
get message() {
|
|
152368
|
+
return `Invalid document references: ${this.reason}`;
|
|
152369
|
+
}
|
|
152370
|
+
};
|
|
152361
152371
|
|
|
152362
152372
|
// src/huly/errors-files.ts
|
|
152363
152373
|
var BYTES_PER_MB = 1024 * 1024;
|
|
@@ -153686,6 +153696,7 @@ var HulyDomainError = Schema_exports.Union(
|
|
|
153686
153696
|
DocumentEmptyContentError,
|
|
153687
153697
|
DocumentContentCorruptedError,
|
|
153688
153698
|
DocumentEditModeError,
|
|
153699
|
+
DocumentReferenceError,
|
|
153689
153700
|
CommentNotFoundError,
|
|
153690
153701
|
MilestoneNotFoundError,
|
|
153691
153702
|
ChannelNotFoundError,
|
|
@@ -153764,6 +153775,12 @@ var isMarkdownSerializableMark = (mark) => !isInlineCommentMark(mark);
|
|
|
153764
153775
|
|
|
153765
153776
|
// src/huly/operations/markup.ts
|
|
153766
153777
|
var jsonAsMarkup = import_text.jsonToMarkup;
|
|
153778
|
+
var MARKDOWN_INPUT_REF_URL = "https://huly-mcp.invalid/no-reference-conversion";
|
|
153779
|
+
var markdownInputRefUrl = UrlString.make(MARKDOWN_INPUT_REF_URL);
|
|
153780
|
+
var markdownInputUrlConfig = (urls) => ({
|
|
153781
|
+
refUrl: markdownInputRefUrl,
|
|
153782
|
+
imageUrl: urls.imageUrl
|
|
153783
|
+
});
|
|
153767
153784
|
var testMarkupUrlConfig = {
|
|
153768
153785
|
refUrl: UrlString.make("https://test.invalid/browse?workspace=test"),
|
|
153769
153786
|
imageUrl: UrlString.make("https://test.invalid/files?workspace=test&file=")
|
|
@@ -153803,9 +153820,125 @@ var markupToMarkdownString = (markup, urls) => {
|
|
|
153803
153820
|
return markupNodeToMarkdownString(json3, urls);
|
|
153804
153821
|
};
|
|
153805
153822
|
var markdownToMarkupString = (markdown, urls) => {
|
|
153806
|
-
const json3 = (0, import_text_markdown.markdownToMarkup)(markdown, urls);
|
|
153823
|
+
const json3 = (0, import_text_markdown.markdownToMarkup)(markdown, markdownInputUrlConfig(urls));
|
|
153807
153824
|
return jsonAsMarkup(json3);
|
|
153808
153825
|
};
|
|
153826
|
+
var trimmedQueryValue = (query, name) => {
|
|
153827
|
+
const value3 = query.get(name);
|
|
153828
|
+
if (value3 === null) {
|
|
153829
|
+
return void 0;
|
|
153830
|
+
}
|
|
153831
|
+
const trimmed2 = value3.trim();
|
|
153832
|
+
return trimmed2 === "" ? void 0 : trimmed2;
|
|
153833
|
+
};
|
|
153834
|
+
var hasAnyNativeReferenceQueryField = (query) => ["_id", "_class", "label"].some((name) => query.has(name));
|
|
153835
|
+
var parseUrlPair = (href, refUrl) => {
|
|
153836
|
+
try {
|
|
153837
|
+
return {
|
|
153838
|
+
candidateUrl: new URL(href),
|
|
153839
|
+
refUrl: new URL(refUrl)
|
|
153840
|
+
};
|
|
153841
|
+
} catch {
|
|
153842
|
+
return void 0;
|
|
153843
|
+
}
|
|
153844
|
+
};
|
|
153845
|
+
var parseNativeReferenceQuery = (query) => {
|
|
153846
|
+
const id = trimmedQueryValue(query, "_id");
|
|
153847
|
+
const objectClass = trimmedQueryValue(query, "_class");
|
|
153848
|
+
const label = trimmedQueryValue(query, "label");
|
|
153849
|
+
if (id === void 0 || objectClass === void 0 || label === void 0) {
|
|
153850
|
+
const missing = [
|
|
153851
|
+
id === void 0 ? "id" : void 0,
|
|
153852
|
+
objectClass === void 0 ? "objectclass" : void 0,
|
|
153853
|
+
label === void 0 ? "label" : void 0
|
|
153854
|
+
].filter((name) => name !== void 0);
|
|
153855
|
+
return { _tag: "missing", missing };
|
|
153856
|
+
}
|
|
153857
|
+
return {
|
|
153858
|
+
_tag: "reference",
|
|
153859
|
+
reference: {
|
|
153860
|
+
id: DocId.make(id),
|
|
153861
|
+
objectClass: ObjectClassName.make(objectClass),
|
|
153862
|
+
label: NonEmptyString2.make(label)
|
|
153863
|
+
}
|
|
153864
|
+
};
|
|
153865
|
+
};
|
|
153866
|
+
var parseNativeBrowseReferenceHref = (href, urls) => {
|
|
153867
|
+
const parsedUrlPair = parseUrlPair(href, urls.refUrl);
|
|
153868
|
+
if (parsedUrlPair === void 0) {
|
|
153869
|
+
return { _tag: "notReference" };
|
|
153870
|
+
}
|
|
153871
|
+
const { candidateUrl, refUrl } = parsedUrlPair;
|
|
153872
|
+
if (candidateUrl.origin !== refUrl.origin || candidateUrl.pathname !== refUrl.pathname) {
|
|
153873
|
+
return { _tag: "notReference" };
|
|
153874
|
+
}
|
|
153875
|
+
if (candidateUrl.searchParams.get("workspace") !== refUrl.searchParams.get("workspace")) {
|
|
153876
|
+
return { _tag: "notReference" };
|
|
153877
|
+
}
|
|
153878
|
+
if (!hasAnyNativeReferenceQueryField(candidateUrl.searchParams)) {
|
|
153879
|
+
return { _tag: "notReference" };
|
|
153880
|
+
}
|
|
153881
|
+
const parsedQuery = parseNativeReferenceQuery(candidateUrl.searchParams);
|
|
153882
|
+
if (parsedQuery._tag === "missing") {
|
|
153883
|
+
return { _tag: "malformed", reason: `reference missing ${parsedQuery.missing.join(", ")}` };
|
|
153884
|
+
}
|
|
153885
|
+
return {
|
|
153886
|
+
_tag: "reference",
|
|
153887
|
+
reference: parsedQuery.reference
|
|
153888
|
+
};
|
|
153889
|
+
};
|
|
153890
|
+
var linkHref = (node) => {
|
|
153891
|
+
const linkMark = node.marks?.find((mark) => mark.type === "link" && typeof mark.attrs?.href === "string");
|
|
153892
|
+
const href = linkMark?.attrs?.href;
|
|
153893
|
+
return typeof href === "string" ? href : void 0;
|
|
153894
|
+
};
|
|
153895
|
+
var referenceNodeFromTextNode = (node, reference) => ({
|
|
153896
|
+
type: import_text.MarkupNodeType.reference,
|
|
153897
|
+
attrs: {
|
|
153898
|
+
id: reference.id,
|
|
153899
|
+
objectclass: reference.objectClass,
|
|
153900
|
+
label: reference.label
|
|
153901
|
+
},
|
|
153902
|
+
content: [{
|
|
153903
|
+
type: import_text.MarkupNodeType.text,
|
|
153904
|
+
text: typeof node.text === "string" && node.text !== "" ? node.text : reference.label,
|
|
153905
|
+
marks: []
|
|
153906
|
+
}]
|
|
153907
|
+
});
|
|
153908
|
+
var transformNativeReferenceLinks = (node, urls) => {
|
|
153909
|
+
const href = node.type === import_text.MarkupNodeType.text ? linkHref(node) : void 0;
|
|
153910
|
+
if (href !== void 0) {
|
|
153911
|
+
const parsed = parseNativeBrowseReferenceHref(href, urls);
|
|
153912
|
+
if (parsed._tag === "malformed") {
|
|
153913
|
+
return { node, malformedReferences: [parsed.reason], changed: false };
|
|
153914
|
+
}
|
|
153915
|
+
if (parsed._tag === "reference") {
|
|
153916
|
+
return {
|
|
153917
|
+
node: referenceNodeFromTextNode(node, parsed.reference),
|
|
153918
|
+
malformedReferences: [],
|
|
153919
|
+
changed: true
|
|
153920
|
+
};
|
|
153921
|
+
}
|
|
153922
|
+
}
|
|
153923
|
+
if (node.content === void 0) {
|
|
153924
|
+
return { node, malformedReferences: [], changed: false };
|
|
153925
|
+
}
|
|
153926
|
+
const transformed = node.content.map((child) => transformNativeReferenceLinks(child, urls));
|
|
153927
|
+
const changed = transformed.some((entry) => entry.changed);
|
|
153928
|
+
return {
|
|
153929
|
+
node: changed ? { ...node, content: transformed.map((entry) => entry.node) } : node,
|
|
153930
|
+
malformedReferences: transformed.flatMap((entry) => entry.malformedReferences),
|
|
153931
|
+
changed
|
|
153932
|
+
};
|
|
153933
|
+
};
|
|
153934
|
+
var markdownToMarkupStringWithHulyLinks = (markdown, urls) => {
|
|
153935
|
+
const json3 = (0, import_text_markdown.markdownToMarkup)(markdown, markdownInputUrlConfig(urls));
|
|
153936
|
+
const transformed = transformNativeReferenceLinks(json3, urls);
|
|
153937
|
+
return {
|
|
153938
|
+
markup: jsonAsMarkup(transformed.node),
|
|
153939
|
+
malformedReferences: transformed.malformedReferences
|
|
153940
|
+
};
|
|
153941
|
+
};
|
|
153809
153942
|
var optionalMarkdownToMarkup = (md, urls, fallback = "") => md && md.trim() !== "" ? markdownToMarkupString(md, urls) : fallback;
|
|
153810
153943
|
function optionalMarkupToMarkdown(markup, urls, fallback = "") {
|
|
153811
153944
|
return markup === null || markup === void 0 ? fallback : markupToMarkdownString(markup, urls);
|
|
@@ -153899,6 +154032,10 @@ var connectWithRetry = (connect, errorPrefix) => withConnectionRetry(
|
|
|
153899
154032
|
}
|
|
153900
154033
|
})
|
|
153901
154034
|
);
|
|
154035
|
+
var markdownInputOptions = (opts) => ({
|
|
154036
|
+
refUrl: MARKDOWN_INPUT_REF_URL,
|
|
154037
|
+
imageUrl: opts.imageUrl
|
|
154038
|
+
});
|
|
153902
154039
|
function toInternalMarkup(value3, format7, opts, sdk) {
|
|
153903
154040
|
switch (format7) {
|
|
153904
154041
|
case "markup":
|
|
@@ -153906,7 +154043,7 @@ function toInternalMarkup(value3, format7, opts, sdk) {
|
|
|
153906
154043
|
case "html":
|
|
153907
154044
|
return sdk.jsonToMarkup(sdk.htmlToJSON(value3));
|
|
153908
154045
|
case "markdown":
|
|
153909
|
-
return sdk.jsonToMarkup(sdk.markdownToMarkup(value3, opts));
|
|
154046
|
+
return sdk.jsonToMarkup(sdk.markdownToMarkup(value3, markdownInputOptions(opts)));
|
|
153910
154047
|
default:
|
|
153911
154048
|
absurd(format7);
|
|
153912
154049
|
throw new Error(`Invalid format: ${format7}`);
|
|
@@ -164471,6 +164608,7 @@ var INVALID_PARAMS_TAGS = /* @__PURE__ */ new Set([
|
|
|
164471
164608
|
"DocumentEmptyContentError",
|
|
164472
164609
|
"DocumentContentCorruptedError",
|
|
164473
164610
|
"DocumentEditModeError",
|
|
164611
|
+
"DocumentReferenceError",
|
|
164474
164612
|
"CommentNotFoundError",
|
|
164475
164613
|
"MilestoneNotFoundError",
|
|
164476
164614
|
"ChannelNotFoundError",
|
|
@@ -167160,6 +167298,10 @@ var parseDeleteIssueTemplateParams = Schema_exports.decodeUnknown(DeleteIssueTem
|
|
|
167160
167298
|
var parseAddTemplateChildParams = Schema_exports.decodeUnknown(AddTemplateChildParamsSchema);
|
|
167161
167299
|
var parseRemoveTemplateChildParams = Schema_exports.decodeUnknown(RemoveTemplateChildParamsSchema);
|
|
167162
167300
|
|
|
167301
|
+
// src/domain/schemas/document-native-references.ts
|
|
167302
|
+
var DOCUMENT_NATIVE_REFERENCE_LINK_USAGE = "Use markdown links to current-workspace Huly browse URLs for native references; Huly browse links returned in get_document content round-trip as native references. The URL identifies the object; link text is display text; plain issue keys stay text.";
|
|
167303
|
+
var DOCUMENT_NATIVE_REFERENCE_TOOL_USAGE = `${DOCUMENT_NATIVE_REFERENCE_LINK_USAGE} External URLs stay normal markdown links.`;
|
|
167304
|
+
|
|
167163
167305
|
// src/domain/schemas/documents.ts
|
|
167164
167306
|
var ListTeamspacesParamsSchema = Schema_exports.Struct({
|
|
167165
167307
|
includeArchived: Schema_exports.optional(Schema_exports.Boolean.annotations({
|
|
@@ -167264,7 +167406,7 @@ var EditDocumentParamsSchema = EditDocumentParamsBase.pipe(
|
|
|
167264
167406
|
const hasSearchReplace = hasOldText && hasNewText;
|
|
167265
167407
|
const hasUpdateField = params.title !== void 0 || hasContent || hasSearchReplace;
|
|
167266
167408
|
if (hasContent && (hasOldText || hasNewText)) {
|
|
167267
|
-
return "Cannot provide
|
|
167409
|
+
return "Cannot provide 'content' with 'old_text'/'new_text'. Use full replace or search-and-replace, not both.";
|
|
167268
167410
|
}
|
|
167269
167411
|
if (hasOldText !== hasNewText) {
|
|
167270
167412
|
return "Both 'old_text' and 'new_text' must be provided together for search-and-replace mode.";
|
|
@@ -170223,7 +170365,7 @@ var parseDeleteTestResultParams = Schema_exports.decodeUnknown(DeleteTestResultP
|
|
|
170223
170365
|
var parseRunTestPlanParams = Schema_exports.decodeUnknown(RunTestPlanParamsSchema);
|
|
170224
170366
|
|
|
170225
170367
|
// src/version.ts
|
|
170226
|
-
var VERSION = true ? "0.
|
|
170368
|
+
var VERSION = true ? "0.21.0" : "0.0.0-dev";
|
|
170227
170369
|
|
|
170228
170370
|
// src/mcp/tool-output-schema.ts
|
|
170229
170371
|
var defaultToolOutputSchema = {
|
|
@@ -170598,6 +170740,19 @@ var listDirectMessages = (params) => Effect_exports.gen(function* () {
|
|
|
170598
170740
|
var import_core13 = __toESM(require_lib4(), 1);
|
|
170599
170741
|
var import_rank = __toESM(require_lib33(), 1);
|
|
170600
170742
|
|
|
170743
|
+
// src/huly/operations/document-native-references.ts
|
|
170744
|
+
var malformedReferenceList = (entries2) => entries2.map((entry) => `'${entry}'`).join(", ");
|
|
170745
|
+
var renderDocumentContentForWrite = (content) => Effect_exports.gen(function* () {
|
|
170746
|
+
const client = yield* HulyClient;
|
|
170747
|
+
const rendered = markdownToMarkupStringWithHulyLinks(content, client.markupUrlConfig);
|
|
170748
|
+
if (rendered.malformedReferences.length > 0) {
|
|
170749
|
+
return yield* new DocumentReferenceError({
|
|
170750
|
+
reason: `malformed Huly native reference links in content: ${malformedReferenceList(rendered.malformedReferences)}`
|
|
170751
|
+
});
|
|
170752
|
+
}
|
|
170753
|
+
return { markup: rendered.markup, format: "markup" };
|
|
170754
|
+
});
|
|
170755
|
+
|
|
170601
170756
|
// src/huly/operations/documents-shared.ts
|
|
170602
170757
|
var findTeamspace = (identifier2, opts) => Effect_exports.gen(function* () {
|
|
170603
170758
|
const client = yield* HulyClient;
|
|
@@ -170705,20 +170860,22 @@ var editDocument = (params) => Effect_exports.gen(function* () {
|
|
|
170705
170860
|
if (params.content.trim() === "") {
|
|
170706
170861
|
updateOps.content = null;
|
|
170707
170862
|
} else if (doc.content) {
|
|
170863
|
+
const renderedContent = yield* renderDocumentContentForWrite(params.content);
|
|
170708
170864
|
yield* client.updateMarkup(
|
|
170709
170865
|
documentPlugin.class.Document,
|
|
170710
170866
|
doc._id,
|
|
170711
170867
|
"content",
|
|
170712
|
-
|
|
170713
|
-
|
|
170868
|
+
renderedContent.markup,
|
|
170869
|
+
renderedContent.format
|
|
170714
170870
|
);
|
|
170715
170871
|
} else {
|
|
170872
|
+
const renderedContent = yield* renderDocumentContentForWrite(params.content);
|
|
170716
170873
|
const contentMarkupRef = yield* client.uploadMarkup(
|
|
170717
170874
|
documentPlugin.class.Document,
|
|
170718
170875
|
doc._id,
|
|
170719
170876
|
"content",
|
|
170720
|
-
|
|
170721
|
-
|
|
170877
|
+
renderedContent.markup,
|
|
170878
|
+
renderedContent.format
|
|
170722
170879
|
);
|
|
170723
170880
|
updateOps.content = contentMarkupRef;
|
|
170724
170881
|
}
|
|
@@ -170746,12 +170903,13 @@ var editDocument = (params) => Effect_exports.gen(function* () {
|
|
|
170746
170903
|
}
|
|
170747
170904
|
const idx = currentContent.indexOf(params.old_text);
|
|
170748
170905
|
const newContent = params.replace_all ? currentContent.split(params.old_text).join(params.new_text) : currentContent.substring(0, idx) + params.new_text + currentContent.substring(idx + params.old_text.length);
|
|
170906
|
+
const renderedContent = yield* renderDocumentContentForWrite(newContent);
|
|
170749
170907
|
yield* client.updateMarkup(
|
|
170750
170908
|
documentPlugin.class.Document,
|
|
170751
170909
|
doc._id,
|
|
170752
170910
|
"content",
|
|
170753
|
-
|
|
170754
|
-
|
|
170911
|
+
renderedContent.markup,
|
|
170912
|
+
renderedContent.format
|
|
170755
170913
|
);
|
|
170756
170914
|
}
|
|
170757
170915
|
const finalTitle = updateOps.title ?? doc.title;
|
|
@@ -171067,13 +171225,17 @@ var createDocument = (params) => Effect_exports.gen(function* () {
|
|
|
171067
171225
|
{ sort: { rank: import_core13.SortingOrder.Descending } }
|
|
171068
171226
|
);
|
|
171069
171227
|
const rank = (0, import_rank.makeRank)(lastDoc?.rank, void 0);
|
|
171070
|
-
const
|
|
171071
|
-
|
|
171072
|
-
|
|
171073
|
-
|
|
171074
|
-
|
|
171075
|
-
|
|
171076
|
-
|
|
171228
|
+
const content = params.content;
|
|
171229
|
+
const contentMarkupRef = content !== void 0 && content.trim() !== "" ? yield* Effect_exports.gen(function* () {
|
|
171230
|
+
const renderedContent = yield* renderDocumentContentForWrite(content);
|
|
171231
|
+
return yield* client.uploadMarkup(
|
|
171232
|
+
documentPlugin.class.Document,
|
|
171233
|
+
documentId,
|
|
171234
|
+
"content",
|
|
171235
|
+
renderedContent.markup,
|
|
171236
|
+
renderedContent.format
|
|
171237
|
+
);
|
|
171238
|
+
}) : null;
|
|
171077
171239
|
const documentData = {
|
|
171078
171240
|
title: params.title,
|
|
171079
171241
|
content: contentMarkupRef,
|
|
@@ -175283,7 +175445,7 @@ var documentTools = [
|
|
|
175283
175445
|
},
|
|
175284
175446
|
{
|
|
175285
175447
|
name: "create_document",
|
|
175286
|
-
description: "Create a new document in a Huly teamspace. Content
|
|
175448
|
+
description: "Create a new document in a Huly teamspace. Content is markdown and supports native Mermaid diagrams (```mermaid blocks render interactively in Huly UI). " + DOCUMENT_NATIVE_REFERENCE_TOOL_USAGE + " Optionally pass parent as a document title or ID to create a nested child document; invalid parents fail instead of silently creating a top-level document. Returns the created document id and a 'url' field pointing to the document in the Huly web app. Use link_document_to_issue only if you also want an issue-document association.",
|
|
175287
175449
|
category: CATEGORY10,
|
|
175288
175450
|
inputSchema: createDocumentParamsJsonSchema,
|
|
175289
175451
|
handler: createToolHandler(
|
|
@@ -175294,7 +175456,7 @@ var documentTools = [
|
|
|
175294
175456
|
},
|
|
175295
175457
|
{
|
|
175296
175458
|
name: "edit_document",
|
|
175297
|
-
description: "Edit an existing Huly document.
|
|
175459
|
+
description: "Edit an existing Huly document. You may rename with title and/or edit the body. Body editing has two mutually exclusive modes: (1) content replaces the entire markdown body, (2) old_text + new_text performs exact targeted search-and-replace. " + DOCUMENT_NATIVE_REFERENCE_TOOL_USAGE + " For targeted replace, multiple matches error unless replace_all is true; empty new_text deletes matched text. Content supports native Mermaid diagrams. Returns a 'url' field pointing to the document in the Huly web app.",
|
|
175298
175460
|
category: CATEGORY10,
|
|
175299
175461
|
inputSchema: editDocumentParamsJsonSchema,
|
|
175300
175462
|
handler: createToolHandler(
|