@firfi/huly-mcp 0.12.0 → 0.13.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.
Files changed (3) hide show
  1. package/README.md +75 -10
  2. package/dist/index.cjs +1432 -1299
  3. package/package.json +32 -19
package/dist/index.cjs CHANGED
@@ -171638,21 +171638,58 @@ var ActivityCount = Schema_exports.NonNegativeInt.annotations({
171638
171638
  description: "Non-negative integer count for activity replies or reactions"
171639
171639
  });
171640
171640
  var ActivityAction = Schema_exports.Literal("create", "update", "remove");
171641
+ var hasAll = (...values4) => values4.every((value3) => value3 !== void 0);
171641
171642
  var ListActivityParamsSchema = Schema_exports.Struct({
171642
- objectId: NonEmptyString2.annotations({
171643
- description: "ID of the object to get activity for"
171644
- }),
171645
- objectClass: ObjectClassName.annotations({
171646
- description: "Class of the object (e.g., 'tracker:class:Issue')"
171647
- }),
171643
+ objectId: Schema_exports.optional(NonEmptyString2.annotations({
171644
+ description: "Advanced: internal Huly object ID to get activity for. Use with objectClass. Prefer project+issueIdentifier, teamspace+document, or channel when available."
171645
+ })),
171646
+ objectClass: Schema_exports.optional(ObjectClassName.annotations({
171647
+ description: "Advanced: internal Huly object class for objectId, such as 'tracker:class:Issue'. Use with objectId."
171648
+ })),
171649
+ project: Schema_exports.optional(ProjectIdentifier.annotations({
171650
+ description: "Project identifier for issue activity, e.g. 'HULY'. Use with issueIdentifier."
171651
+ })),
171652
+ issueIdentifier: Schema_exports.optional(IssueIdentifier.annotations({
171653
+ description: "Issue identifier for issue activity, e.g. 'HULY-123' or '123'. Use with project."
171654
+ })),
171655
+ teamspace: Schema_exports.optional(TeamspaceIdentifier.annotations({
171656
+ description: "Teamspace name or ID for document activity. Use with document."
171657
+ })),
171658
+ document: Schema_exports.optional(DocumentIdentifier.annotations({
171659
+ description: "Document title or ID for document activity. Use with teamspace."
171660
+ })),
171661
+ channel: Schema_exports.optional(ChannelIdentifier.annotations({
171662
+ description: "Channel name or ID for channel activity."
171663
+ })),
171648
171664
  limit: Schema_exports.optional(
171649
171665
  LimitParam.annotations({
171650
171666
  description: "Maximum number of activity messages to return (default: 50)"
171651
171667
  })
171652
171668
  )
171653
- }).annotations({
171669
+ }).pipe(
171670
+ Schema_exports.filter((params) => {
171671
+ const rawObjectMode = hasAll(params.objectId, params.objectClass);
171672
+ const issueMode = hasAll(params.project, params.issueIdentifier);
171673
+ const documentMode = hasAll(params.teamspace, params.document);
171674
+ const channelMode = params.channel !== void 0;
171675
+ const modeCount = [rawObjectMode, issueMode, documentMode, channelMode].filter(Boolean).length;
171676
+ if (params.objectId !== void 0 !== (params.objectClass !== void 0)) {
171677
+ return "Provide both objectId and objectClass for raw object activity, or use a friendly target mode.";
171678
+ }
171679
+ if (params.project !== void 0 !== (params.issueIdentifier !== void 0)) {
171680
+ return "Provide both project and issueIdentifier for issue activity.";
171681
+ }
171682
+ if (params.teamspace !== void 0 !== (params.document !== void 0)) {
171683
+ return "Provide both teamspace and document for document activity.";
171684
+ }
171685
+ if (modeCount !== 1) {
171686
+ return "Choose exactly one activity target mode: objectId+objectClass, project+issueIdentifier, teamspace+document, or channel.";
171687
+ }
171688
+ return void 0;
171689
+ })
171690
+ ).annotations({
171654
171691
  title: "ListActivityParams",
171655
- description: "Parameters for listing activity on an object"
171692
+ description: "Parameters for listing activity on a Huly object. Prefer friendly identifiers; raw objectId+objectClass is for advanced callers."
171656
171693
  });
171657
171694
  var AddReactionParamsSchema = Schema_exports.Struct({
171658
171695
  messageId: ActivityMessageId.annotations({
@@ -171725,7 +171762,66 @@ var ListMentionsParamsSchema = Schema_exports.Struct({
171725
171762
  title: "ListMentionsParams",
171726
171763
  description: "Parameters for listing mentions of the current user"
171727
171764
  });
171728
- var listActivityParamsJsonSchema = JSONSchema_exports.make(ListActivityParamsSchema);
171765
+ var activityLimitJsonSchema = {
171766
+ type: "integer",
171767
+ minimum: 1,
171768
+ maximum: MAX_LIMIT,
171769
+ description: "Maximum number of activity messages to return (default: 50)"
171770
+ };
171771
+ var targetStringJsonSchema = (description) => ({
171772
+ type: "string",
171773
+ minLength: 1,
171774
+ description
171775
+ });
171776
+ var listActivityParamsJsonSchema = {
171777
+ type: "object",
171778
+ description: "Choose exactly one target mode for activity lookup: project+issueIdentifier, teamspace+document, channel, or objectId+objectClass.",
171779
+ oneOf: [
171780
+ {
171781
+ title: "Issue activity target",
171782
+ type: "object",
171783
+ additionalProperties: false,
171784
+ required: ["project", "issueIdentifier"],
171785
+ properties: {
171786
+ project: targetStringJsonSchema("Project identifier for issue activity, e.g. 'HULY'."),
171787
+ issueIdentifier: targetStringJsonSchema("Issue identifier for issue activity, e.g. 'HULY-123' or '123'."),
171788
+ limit: activityLimitJsonSchema
171789
+ }
171790
+ },
171791
+ {
171792
+ title: "Document activity target",
171793
+ type: "object",
171794
+ additionalProperties: false,
171795
+ required: ["teamspace", "document"],
171796
+ properties: {
171797
+ teamspace: targetStringJsonSchema("Teamspace name or ID for document activity."),
171798
+ document: targetStringJsonSchema("Document title or ID for document activity."),
171799
+ limit: activityLimitJsonSchema
171800
+ }
171801
+ },
171802
+ {
171803
+ title: "Channel activity target",
171804
+ type: "object",
171805
+ additionalProperties: false,
171806
+ required: ["channel"],
171807
+ properties: {
171808
+ channel: targetStringJsonSchema("Channel name or ID for channel activity."),
171809
+ limit: activityLimitJsonSchema
171810
+ }
171811
+ },
171812
+ {
171813
+ title: "Raw Huly object activity target",
171814
+ type: "object",
171815
+ additionalProperties: false,
171816
+ required: ["objectId", "objectClass"],
171817
+ properties: {
171818
+ objectId: targetStringJsonSchema("Internal Huly object ID to get activity for."),
171819
+ objectClass: targetStringJsonSchema("Internal Huly object class for objectId, such as 'tracker:class:Issue'."),
171820
+ limit: activityLimitJsonSchema
171821
+ }
171822
+ }
171823
+ ]
171824
+ };
171729
171825
  var addReactionParamsJsonSchema = JSONSchema_exports.make(AddReactionParamsSchema);
171730
171826
  var removeReactionParamsJsonSchema = JSONSchema_exports.make(RemoveReactionParamsSchema);
171731
171827
  var listReactionsParamsJsonSchema = JSONSchema_exports.make(ListReactionsParamsSchema);
@@ -171792,6 +171888,9 @@ var ListSavedMessagesResultSchema = Schema_exports.Array(SavedMessageWireSchema)
171792
171888
  var ListMentionsResultSchema = Schema_exports.Array(MentionWireSchema);
171793
171889
 
171794
171890
  // src/huly/operations/activity.ts
171891
+ var import_core22 = __toESM(require_lib4(), 1);
171892
+
171893
+ // src/huly/operations/channels.ts
171795
171894
  var import_core19 = __toESM(require_lib4(), 1);
171796
171895
 
171797
171896
  // src/huly/operations/query-helpers.ts
@@ -171833,552 +171932,311 @@ var task = require_lib34().default;
171833
171932
  var time3 = require_lib35().default;
171834
171933
  var tracker = require_lib36().default;
171835
171934
 
171836
- // src/huly/operations/activity.ts
171837
- var optionalTimestamp = (value3) => value3 === void 0 ? void 0 : Timestamp.make(value3);
171838
- var optionalNullableTimestamp = (value3) => value3 === void 0 || value3 === null ? value3 : Timestamp.make(value3);
171839
- var optionalActivityCount = (value3) => value3 === void 0 ? void 0 : ActivityCount.make(value3);
171840
- var optionalPersonId = (value3) => value3 === void 0 || value3 === "" ? void 0 : PersonId.make(value3);
171841
- var serverPopulatedCreateBy = "";
171842
- var listActivity = (params) => Effect_exports.gen(function* () {
171843
- const client = yield* HulyClient;
171844
- const limit = clampLimit(params.limit);
171845
- const messages = yield* client.findAll(
171846
- activity.class.ActivityMessage,
171847
- {
171848
- attachedTo: toRef(params.objectId),
171849
- attachedToClass: toRef(params.objectClass)
171850
- },
171935
+ // src/huly/operations/channel-messages-shared.ts
171936
+ var findChannelMessage = (params) => Effect_exports.gen(function* () {
171937
+ const { channel, client } = yield* findChannel(params.channel);
171938
+ const message = yield* client.findOne(
171939
+ chunter.class.ChatMessage,
171851
171940
  {
171852
- limit,
171853
- sort: {
171854
- modifiedOn: import_core19.SortingOrder.Descending
171855
- }
171941
+ _id: toRef(params.messageId),
171942
+ space: channel._id
171856
171943
  }
171857
171944
  );
171858
- const result = messages.map((msg) => ({
171859
- id: ActivityMessageId.make(msg._id),
171860
- objectId: NonEmptyString2.make(msg.attachedTo),
171861
- objectClass: ObjectClassName.make(msg.attachedToClass),
171862
- modifiedBy: PersonId.make(msg.modifiedBy),
171863
- modifiedOn: optionalTimestamp(msg.modifiedOn),
171864
- isPinned: msg.isPinned,
171865
- replies: optionalActivityCount(msg.replies),
171866
- reactions: optionalActivityCount(msg.reactions),
171867
- editedOn: optionalNullableTimestamp(msg.editedOn)
171868
- }));
171869
- return result;
171945
+ if (message === void 0) {
171946
+ return yield* new MessageNotFoundError({
171947
+ messageId: params.messageId,
171948
+ channel: params.channel
171949
+ });
171950
+ }
171951
+ return { client, channel, message };
171870
171952
  });
171871
- var addReaction = (params) => Effect_exports.gen(function* () {
171872
- const client = yield* HulyClient;
171873
- const message = yield* findOneOrFail(
171874
- client,
171875
- activity.class.ActivityMessage,
171876
- { _id: toRef(params.messageId) },
171877
- () => new ActivityMessageNotFoundError({ messageId: params.messageId })
171878
- );
171879
- const reactionId = (0, import_core19.generateId)();
171880
- const reactionData = {
171881
- emoji: params.emoji,
171882
- createBy: serverPopulatedCreateBy
171953
+
171954
+ // src/huly/operations/channels-messages.ts
171955
+ var updateChannelMessage = (params) => Effect_exports.gen(function* () {
171956
+ const { channel, client, message } = yield* findChannelMessage(params);
171957
+ const markupUrlConfig = client.markupUrlConfig;
171958
+ const markup = markdownToMarkupString(params.body, markupUrlConfig);
171959
+ const now2 = yield* Clock_exports.currentTimeMillis;
171960
+ const updateOps = {
171961
+ message: markup,
171962
+ editedOn: now2
171883
171963
  };
171884
- yield* client.addCollection(
171885
- activity.class.Reaction,
171886
- message.space,
171964
+ yield* client.updateDoc(
171965
+ chunter.class.ChatMessage,
171966
+ channel._id,
171887
171967
  message._id,
171888
- activity.class.ActivityMessage,
171889
- "reactions",
171890
- reactionData,
171891
- reactionId
171968
+ updateOps
171892
171969
  );
171893
- return {
171894
- reactionId: ReactionId.make(reactionId),
171895
- messageId: ActivityMessageId.make(params.messageId)
171896
- };
171970
+ return { id: MessageId.make(message._id), updated: true };
171897
171971
  });
171898
- var removeReaction = (params) => Effect_exports.gen(function* () {
171899
- const client = yield* HulyClient;
171900
- const reaction = yield* findOneOrFail(
171901
- client,
171902
- activity.class.Reaction,
171903
- {
171904
- attachedTo: toRef(params.messageId),
171905
- emoji: params.emoji
171906
- },
171907
- () => new ReactionNotFoundError({
171908
- messageId: params.messageId,
171909
- emoji: params.emoji
171910
- })
171911
- );
171972
+ var deleteChannelMessage = (params) => Effect_exports.gen(function* () {
171973
+ const { channel, client, message } = yield* findChannelMessage(params);
171912
171974
  yield* client.removeDoc(
171913
- activity.class.Reaction,
171914
- reaction.space,
171915
- reaction._id
171916
- );
171917
- return {
171918
- messageId: ActivityMessageId.make(params.messageId),
171919
- removed: true
171920
- };
171921
- });
171922
- var listReactions = (params) => Effect_exports.gen(function* () {
171923
- const client = yield* HulyClient;
171924
- const limit = clampLimit(params.limit);
171925
- const reactions = yield* client.findAll(
171926
- activity.class.Reaction,
171927
- {
171928
- attachedTo: toRef(params.messageId)
171929
- },
171930
- { limit }
171975
+ chunter.class.ChatMessage,
171976
+ channel._id,
171977
+ message._id
171931
171978
  );
171932
- const result = reactions.map((r) => ({
171933
- id: ReactionId.make(r._id),
171934
- messageId: ActivityMessageId.make(r.attachedTo),
171935
- emoji: EmojiCode.make(r.emoji),
171936
- createdBy: optionalPersonId(r.createBy)
171937
- }));
171938
- return result;
171979
+ return { id: MessageId.make(message._id), deleted: true };
171939
171980
  });
171940
- var saveMessage = (params) => Effect_exports.gen(function* () {
171981
+
171982
+ // src/huly/operations/channels.ts
171983
+ var personIdsAsSocialIdentityRefs = (ids3) => ids3;
171984
+ var findChannel = (identifier2) => Effect_exports.gen(function* () {
171941
171985
  const client = yield* HulyClient;
171942
- const message = yield* findOneOrFail(
171986
+ const channel = yield* findByNameOrId(
171943
171987
  client,
171944
- activity.class.ActivityMessage,
171945
- { _id: toRef(params.messageId) },
171946
- () => new ActivityMessageNotFoundError({ messageId: params.messageId })
171947
- );
171948
- const savedId = (0, import_core19.generateId)();
171949
- yield* client.createDoc(
171950
- activity.class.SavedMessage,
171951
- core.space.Workspace,
171952
- {
171953
- attachedTo: message._id
171954
- },
171955
- savedId
171988
+ chunter.class.Channel,
171989
+ { name: identifier2 },
171990
+ { _id: toRef(identifier2) }
171956
171991
  );
171957
- return {
171958
- savedId: SavedMessageId.make(savedId),
171959
- messageId: ActivityMessageId.make(params.messageId)
171960
- };
171992
+ if (channel === void 0) {
171993
+ return yield* new ChannelNotFoundError({ identifier: identifier2 });
171994
+ }
171995
+ return { client, channel };
171961
171996
  });
171962
- var unsaveMessage = (params) => Effect_exports.gen(function* () {
171963
- const client = yield* HulyClient;
171964
- const saved = yield* findOneOrFail(
171965
- client,
171966
- activity.class.SavedMessage,
171967
- {
171968
- attachedTo: toRef(params.messageId)
171969
- },
171970
- () => new SavedMessageNotFoundError({ messageId: params.messageId })
171971
- );
171972
- yield* client.removeDoc(
171973
- activity.class.SavedMessage,
171974
- saved.space,
171975
- saved._id
171997
+ var buildSocialIdToPersonNameMap = (client, socialIds) => Effect_exports.gen(function* () {
171998
+ if (socialIds.length === 0) {
171999
+ return /* @__PURE__ */ new Map();
172000
+ }
172001
+ const socialIdentities = yield* client.findAll(
172002
+ contact.class.SocialIdentity,
172003
+ { _id: { $in: personIdsAsSocialIdentityRefs(socialIds) } }
171976
172004
  );
171977
- return {
171978
- messageId: ActivityMessageId.make(params.messageId),
171979
- removed: true
171980
- };
171981
- });
171982
- var listSavedMessages = (params) => Effect_exports.gen(function* () {
171983
- const client = yield* HulyClient;
171984
- const limit = clampLimit(params.limit);
171985
- const saved = yield* client.findAll(
171986
- activity.class.SavedMessage,
171987
- {},
171988
- { limit }
172005
+ if (socialIdentities.length === 0) {
172006
+ return /* @__PURE__ */ new Map();
172007
+ }
172008
+ const personRefs = [...new Set(socialIdentities.map((si) => si.attachedTo))];
172009
+ const persons = yield* client.findAll(
172010
+ contact.class.Person,
172011
+ { _id: { $in: personRefs } }
171989
172012
  );
171990
- const result = saved.map((s) => ({
171991
- id: SavedMessageId.make(s._id),
171992
- messageId: ActivityMessageId.make(s.attachedTo)
171993
- }));
172013
+ const personById = new Map(persons.map((p) => [p._id, p]));
172014
+ const result = /* @__PURE__ */ new Map();
172015
+ for (const si of socialIdentities) {
172016
+ const person = personById.get(si.attachedTo);
172017
+ if (person !== void 0) {
172018
+ result.set(si._id, person.name);
172019
+ }
172020
+ }
171994
172021
  return result;
171995
172022
  });
171996
- var listMentions = (params) => Effect_exports.gen(function* () {
172023
+ var buildAccountUuidToNameMap = (client, accountUuids) => Effect_exports.gen(function* () {
172024
+ if (accountUuids.length === 0) {
172025
+ return /* @__PURE__ */ new Map();
172026
+ }
172027
+ const employees = yield* client.findAll(
172028
+ contact.mixin.Employee,
172029
+ { personUuid: { $in: accountUuids } }
172030
+ );
172031
+ const result = /* @__PURE__ */ new Map();
172032
+ for (const emp of employees) {
172033
+ if (emp.personUuid !== void 0) {
172034
+ result.set(emp.personUuid, emp.name);
172035
+ }
172036
+ }
172037
+ return result;
172038
+ });
172039
+ var listChannels = (params) => Effect_exports.gen(function* () {
171997
172040
  const client = yield* HulyClient;
172041
+ const query = {};
172042
+ if (!params.includeArchived) {
172043
+ query.archived = false;
172044
+ }
172045
+ if (params.nameSearch !== void 0 && params.nameSearch.trim() !== "") {
172046
+ query.name = { $like: `%${escapeLikeWildcards(params.nameSearch)}%` };
172047
+ }
172048
+ if (params.nameRegex !== void 0 && params.nameRegex.trim() !== "") {
172049
+ query.name = { $regex: params.nameRegex };
172050
+ }
172051
+ if (params.topicSearch !== void 0 && params.topicSearch.trim() !== "") {
172052
+ query.topic = { $like: `%${escapeLikeWildcards(params.topicSearch)}%` };
172053
+ }
171998
172054
  const limit = clampLimit(params.limit);
171999
- const mentions = yield* client.findAll(
172000
- activity.class.UserMentionInfo,
172001
- {},
172055
+ const channels = yield* client.findAll(
172056
+ chunter.class.Channel,
172057
+ query,
172002
172058
  {
172003
172059
  limit,
172004
172060
  sort: {
172005
- modifiedOn: import_core19.SortingOrder.Descending
172061
+ name: import_core19.SortingOrder.Ascending
172006
172062
  }
172007
172063
  }
172008
172064
  );
172009
- const result = mentions.map((m) => ({
172010
- id: MentionId.make(m._id),
172011
- messageId: ActivityMessageId.make(m.attachedTo),
172012
- userId: PersonId.make(m.user),
172013
- content: m.content
172065
+ const summaries = channels.map((ch) => ({
172066
+ id: ChannelId.make(ch._id),
172067
+ name: ChannelName.make(ch.name),
172068
+ topic: ch.topic || void 0,
172069
+ private: ch.private,
172070
+ archived: ch.archived,
172071
+ members: ch.members.length,
172072
+ messages: ch.messages,
172073
+ modifiedOn: ch.modifiedOn
172014
172074
  }));
172075
+ return summaries;
172076
+ });
172077
+ var getChannel = (params) => Effect_exports.gen(function* () {
172078
+ const { channel, client } = yield* findChannel(params.channel);
172079
+ const memberNames = channel.members.length > 0 ? yield* Effect_exports.gen(function* () {
172080
+ const accountUuidToName = yield* buildAccountUuidToNameMap(client, channel.members);
172081
+ return channel.members.map((m) => accountUuidToName.get(m)).filter((n) => n !== void 0);
172082
+ }) : void 0;
172083
+ const result = {
172084
+ id: ChannelId.make(channel._id),
172085
+ name: ChannelName.make(channel.name),
172086
+ topic: channel.topic || void 0,
172087
+ description: channel.description || void 0,
172088
+ private: channel.private,
172089
+ archived: channel.archived,
172090
+ members: memberNames?.map((m) => PersonName.make(m)),
172091
+ messages: channel.messages,
172092
+ modifiedOn: channel.modifiedOn,
172093
+ createdOn: channel.createdOn
172094
+ };
172015
172095
  return result;
172016
172096
  });
172017
-
172018
- // src/mcp/tools/registry.ts
172019
- var deriveTitle = (name) => name.split("_").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
172020
- var READ_PREFIXES = ["list_", "get_", "search_", "fulltext_", "download_", "preview_"];
172021
- var CREATE_PREFIXES = ["create_", "add_", "upload_", "send_", "log_"];
172022
- var UPDATE_PREFIXES = [
172023
- "update_",
172024
- "edit_",
172025
- "set_",
172026
- "pin_",
172027
- "unpin_",
172028
- "mark_",
172029
- "archive_",
172030
- "start_",
172031
- "stop_",
172032
- "save_",
172033
- "unsave_",
172034
- "remove_",
172035
- "move_"
172036
- ];
172037
- var DELETE_PREFIXES = ["delete_"];
172038
- var matchesPrefix = (name, prefixes) => prefixes.some((p) => name.startsWith(p));
172039
- var deriveAnnotations = (name) => {
172040
- const title = deriveTitle(name);
172041
- if (matchesPrefix(name, READ_PREFIXES)) {
172042
- return { title, readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
172043
- }
172044
- if (matchesPrefix(name, CREATE_PREFIXES)) {
172045
- return { title, readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false };
172046
- }
172047
- if (matchesPrefix(name, UPDATE_PREFIXES)) {
172048
- return { title, readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false };
172049
- }
172050
- if (matchesPrefix(name, DELETE_PREFIXES)) {
172051
- return { title, readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false };
172052
- }
172053
- return { title, readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false };
172054
- };
172055
- var resolveAnnotations = (tool) => ({
172056
- ...deriveAnnotations(tool.name),
172057
- ...tool.annotations
172097
+ var createChannel = (params) => Effect_exports.gen(function* () {
172098
+ const client = yield* HulyClient;
172099
+ const channelId = (0, import_core19.generateId)();
172100
+ const channelData = {
172101
+ name: params.name,
172102
+ topic: params.topic || "",
172103
+ description: "",
172104
+ private: params.private ?? false,
172105
+ archived: false,
172106
+ members: [client.getAccountUuid()],
172107
+ owners: [client.getAccountUuid()]
172108
+ };
172109
+ yield* client.createDoc(
172110
+ chunter.class.Channel,
172111
+ toRef(channelId),
172112
+ channelData,
172113
+ channelId
172114
+ );
172115
+ return { id: ChannelId.make(channelId), name: ChannelName.make(params.name) };
172058
172116
  });
172059
- var encodeOutput = (schema, result) => Schema_exports.encodeUnknownSync(schema)(result);
172060
- var provideHulyClient = (args2) => (effect2) => Either_exports.right(effect2.pipe(Effect_exports.provideService(HulyClient, args2.hulyClient)));
172061
- var provideStorageClient = (args2) => (effect2) => Either_exports.right(effect2.pipe(Effect_exports.provideService(HulyStorageClient, args2.storageClient)));
172062
- var provideCombinedClient = (args2) => (effect2) => Either_exports.right(
172063
- effect2.pipe(
172064
- Effect_exports.provideService(HulyClient, args2.hulyClient),
172065
- Effect_exports.provideService(HulyStorageClient, args2.storageClient)
172066
- )
172067
- );
172068
- var provideWorkspaceClient = (args2) => (effect2) => args2.workspaceClient !== void 0 ? Either_exports.right(effect2.pipe(Effect_exports.provideService(WorkspaceClient, args2.workspaceClient))) : Either_exports.left(mapDomainErrorToMcp(new HulyError({ message: "WorkspaceClient not available" })));
172069
- var createHandler = (toolName, provide4, parse5, operation, encode8) => async (args2, hulyClient, storageClient, workspaceClient) => {
172070
- const parseResult = await Effect_exports.runPromiseExit(parse5(args2));
172071
- if (Exit_exports.isFailure(parseResult)) {
172072
- return mapParseCauseToMcp(parseResult.cause, toolName);
172073
- }
172074
- const provided = provide4({ hulyClient, storageClient, workspaceClient })(operation(parseResult.value));
172075
- if (Either_exports.isLeft(provided)) {
172076
- return provided.left;
172117
+ var updateChannel = (params) => Effect_exports.gen(function* () {
172118
+ const { channel, client } = yield* findChannel(params.channel);
172119
+ const updateOps = {};
172120
+ if (params.name !== void 0) {
172121
+ updateOps.name = params.name;
172077
172122
  }
172078
- const operationResult = await Effect_exports.runPromiseExit(provided.right);
172079
- if (Exit_exports.isFailure(operationResult)) {
172080
- return mapDomainCauseToMcp(operationResult.cause);
172123
+ if (params.topic !== void 0) {
172124
+ updateOps.topic = params.topic;
172081
172125
  }
172082
- try {
172083
- const output = encode8 !== void 0 ? encode8(operationResult.value) : operationResult.value;
172084
- return createSuccessResponse(output);
172085
- } catch {
172086
- return mapDomainErrorToMcp(new HulyError({ message: `Tool ${toolName} produced invalid output` }));
172126
+ if (Object.keys(updateOps).length === 0) {
172127
+ return { id: ChannelId.make(channel._id), updated: false };
172087
172128
  }
172088
- };
172089
- var createToolHandler = (toolName, parse5, operation) => createHandler(toolName, provideHulyClient, parse5, operation);
172090
- var createEncodedToolHandler = (toolName, parse5, operation, outputSchema) => createHandler(
172091
- toolName,
172092
- provideHulyClient,
172093
- parse5,
172094
- operation,
172095
- (result) => encodeOutput(outputSchema, result)
172096
- );
172097
- var createStorageToolHandler = (toolName, parse5, operation) => createHandler(toolName, provideStorageClient, parse5, operation);
172098
- var createCombinedToolHandler = (toolName, parse5, operation) => createHandler(toolName, provideCombinedClient, parse5, operation);
172099
- var createEncodedWorkspaceToolHandler = (toolName, parse5, operation, outputSchema) => createHandler(
172100
- toolName,
172101
- provideWorkspaceClient,
172102
- parse5,
172103
- operation,
172104
- (result) => encodeOutput(outputSchema, result)
172105
- );
172106
- var createEncodedNoParamsWorkspaceToolHandler = (toolName, operation, outputSchema) => createHandler(
172107
- toolName,
172108
- provideWorkspaceClient,
172109
- () => Effect_exports.succeed(void 0),
172110
- operation,
172111
- (result) => encodeOutput(outputSchema, result)
172112
- );
172113
-
172114
- // src/mcp/tools/activity.ts
172115
- var CATEGORY = "activity";
172116
- var activityTools = [
172117
- {
172118
- name: "list_activity",
172119
- description: "List activity messages for a Huly object. Returns activity sorted by date (newest first).",
172120
- category: CATEGORY,
172121
- inputSchema: listActivityParamsJsonSchema,
172122
- handler: createEncodedToolHandler(
172123
- "list_activity",
172124
- parseListActivityParams,
172125
- listActivity,
172126
- ListActivityResultSchema
172127
- )
172128
- },
172129
- {
172130
- name: "add_reaction",
172131
- description: "Add an emoji reaction to an activity message.",
172132
- category: CATEGORY,
172133
- inputSchema: addReactionParamsJsonSchema,
172134
- handler: createEncodedToolHandler(
172135
- "add_reaction",
172136
- parseAddReactionParams,
172137
- addReaction,
172138
- AddReactionResultSchema
172129
+ yield* client.updateDoc(
172130
+ chunter.class.Channel,
172131
+ toRef(channel._id),
172132
+ channel._id,
172133
+ updateOps
172134
+ );
172135
+ return { id: ChannelId.make(channel._id), updated: true };
172136
+ });
172137
+ var deleteChannel = (params) => Effect_exports.gen(function* () {
172138
+ const { channel, client } = yield* findChannel(params.channel);
172139
+ yield* client.removeDoc(
172140
+ chunter.class.Channel,
172141
+ toRef(channel._id),
172142
+ channel._id
172143
+ );
172144
+ return { id: ChannelId.make(channel._id), deleted: true };
172145
+ });
172146
+ var listChannelMessages = (params) => Effect_exports.gen(function* () {
172147
+ const { channel, client } = yield* findChannel(params.channel);
172148
+ const markupUrlConfig = client.markupUrlConfig;
172149
+ const limit = clampLimit(params.limit);
172150
+ const messages = yield* client.findAll(
172151
+ chunter.class.ChatMessage,
172152
+ {
172153
+ space: channel._id
172154
+ },
172155
+ {
172156
+ limit,
172157
+ sort: {
172158
+ createdOn: import_core19.SortingOrder.Descending
172159
+ }
172160
+ }
172161
+ );
172162
+ const total = messages.total;
172163
+ const uniqueSocialIds = [
172164
+ ...new Set(
172165
+ messages.map((msg) => msg.modifiedBy)
172139
172166
  )
172140
- },
172141
- {
172142
- name: "remove_reaction",
172143
- description: "Remove an emoji reaction from an activity message.",
172144
- category: CATEGORY,
172145
- inputSchema: removeReactionParamsJsonSchema,
172146
- handler: createEncodedToolHandler(
172147
- "remove_reaction",
172148
- parseRemoveReactionParams,
172149
- removeReaction,
172150
- RemoveReactionResultSchema
172151
- )
172152
- },
172153
- {
172154
- name: "list_reactions",
172155
- description: "List reactions on an activity message.",
172156
- category: CATEGORY,
172157
- inputSchema: listReactionsParamsJsonSchema,
172158
- handler: createEncodedToolHandler(
172159
- "list_reactions",
172160
- parseListReactionsParams,
172161
- listReactions,
172162
- ListReactionsResultSchema
172163
- )
172164
- },
172165
- {
172166
- name: "save_message",
172167
- description: "Save/bookmark an activity message for later reference.",
172168
- category: CATEGORY,
172169
- inputSchema: saveMessageParamsJsonSchema,
172170
- handler: createEncodedToolHandler(
172171
- "save_message",
172172
- parseSaveMessageParams,
172173
- saveMessage,
172174
- SaveMessageResultSchema
172175
- )
172176
- },
172177
- {
172178
- name: "unsave_message",
172179
- description: "Remove an activity message from saved/bookmarks.",
172180
- category: CATEGORY,
172181
- inputSchema: unsaveMessageParamsJsonSchema,
172182
- handler: createEncodedToolHandler(
172183
- "unsave_message",
172184
- parseUnsaveMessageParams,
172185
- unsaveMessage,
172186
- UnsaveMessageResultSchema
172187
- )
172188
- },
172189
- {
172190
- name: "list_saved_messages",
172191
- description: "List saved/bookmarked activity messages.",
172192
- category: CATEGORY,
172193
- inputSchema: listSavedMessagesParamsJsonSchema,
172194
- handler: createEncodedToolHandler(
172195
- "list_saved_messages",
172196
- parseListSavedMessagesParams,
172197
- listSavedMessages,
172198
- ListSavedMessagesResultSchema
172199
- )
172200
- },
172201
- {
172202
- name: "list_mentions",
172203
- description: "List @mentions of the current user in activity messages.",
172204
- category: CATEGORY,
172205
- inputSchema: listMentionsParamsJsonSchema,
172206
- handler: createEncodedToolHandler(
172207
- "list_mentions",
172208
- parseListMentionsParams,
172209
- listMentions,
172210
- ListMentionsResultSchema
172211
- )
172212
- }
172213
- ];
172214
-
172215
- // src/domain/schemas/attachments.ts
172216
- var ListAttachmentsParamsSchema = Schema_exports.Struct({
172217
- objectId: NonEmptyString2.annotations({
172218
- description: "ID of the parent object (issue, document, etc.)"
172219
- }),
172220
- objectClass: ObjectClassName.annotations({
172221
- description: "Class of the parent object (e.g., 'tracker:class:Issue', 'document:class:Document')"
172222
- }),
172223
- limit: Schema_exports.optional(
172224
- LimitParam.annotations({
172225
- description: "Maximum number of attachments to return (default: 50)"
172226
- })
172227
- )
172228
- }).annotations({
172229
- title: "ListAttachmentsParams",
172230
- description: "Parameters for listing attachments on an object"
172231
- });
172232
- var GetAttachmentParamsSchema = Schema_exports.Struct({
172233
- attachmentId: AttachmentId.annotations({
172234
- description: "Attachment ID"
172235
- })
172236
- }).annotations({
172237
- title: "GetAttachmentParams",
172238
- description: "Parameters for getting a single attachment"
172239
- });
172240
- var FileSourceFields = {
172241
- filename: NonEmptyString2.annotations({
172242
- description: "Name of the file"
172243
- }),
172244
- contentType: MimeType.annotations({
172245
- description: "MIME type of the file (e.g., 'image/png', 'application/pdf')"
172246
- }),
172247
- filePath: Schema_exports.optional(Schema_exports.String.annotations({
172248
- description: "Local file path to upload (preferred - avoids context flooding)"
172249
- })),
172250
- fileUrl: Schema_exports.optional(Schema_exports.String.annotations({
172251
- description: "URL to fetch file from (for remote files)"
172252
- })),
172253
- data: Schema_exports.optional(Schema_exports.String.annotations({
172254
- description: "Base64-encoded file data (fallback for small files <10KB)"
172255
- })),
172256
- description: Schema_exports.optional(Schema_exports.String.annotations({
172257
- description: "Attachment description"
172258
- })),
172259
- pinned: Schema_exports.optional(Schema_exports.Boolean.annotations({
172260
- description: "Whether to pin the attachment (default: false)"
172261
- }))
172262
- };
172263
- var hasFileSource = (params) => {
172264
- const hasSource = params.filePath || params.fileUrl || params.data;
172265
- return hasSource ? true : "Must provide filePath, fileUrl, or data";
172266
- };
172267
- var AddAttachmentParamsBase = Schema_exports.Struct({
172268
- objectId: NonEmptyString2.annotations({
172269
- description: "ID of the parent object (issue, document, etc.)"
172270
- }),
172271
- objectClass: ObjectClassName.annotations({
172272
- description: "Class of the parent object (e.g., 'tracker:class:Issue', 'document:class:Document')"
172273
- }),
172274
- space: SpaceId.annotations({
172275
- description: "Space ID where the parent object resides"
172276
- }),
172277
- ...FileSourceFields
172278
- });
172279
- var AddAttachmentParamsSchema = AddAttachmentParamsBase.pipe(
172280
- Schema_exports.filter(hasFileSource)
172281
- ).annotations({
172282
- title: "AddAttachmentParams",
172283
- description: "Parameters for adding an attachment. Provide ONE of: filePath, fileUrl, or data"
172284
- });
172285
- var UpdateAttachmentParamsSchema = Schema_exports.Struct({
172286
- attachmentId: AttachmentId.annotations({
172287
- description: "Attachment ID"
172288
- }),
172289
- description: Schema_exports.optional(
172290
- Schema_exports.NullOr(Schema_exports.String).annotations({
172291
- description: "New description (null to clear)"
172292
- })
172293
- ),
172294
- pinned: Schema_exports.optional(Schema_exports.Boolean.annotations({
172295
- description: "Pin or unpin the attachment"
172296
- }))
172297
- }).annotations({
172298
- title: "UpdateAttachmentParams",
172299
- description: "Parameters for updating an attachment"
172300
- });
172301
- var DeleteAttachmentParamsSchema = Schema_exports.Struct({
172302
- attachmentId: AttachmentId.annotations({
172303
- description: "Attachment ID to delete"
172304
- })
172305
- }).annotations({
172306
- title: "DeleteAttachmentParams",
172307
- description: "Parameters for deleting an attachment"
172308
- });
172309
- var PinAttachmentParamsSchema = Schema_exports.Struct({
172310
- attachmentId: AttachmentId.annotations({
172311
- description: "Attachment ID"
172312
- }),
172313
- pinned: Schema_exports.Boolean.annotations({
172314
- description: "Whether to pin (true) or unpin (false)"
172315
- })
172316
- }).annotations({
172317
- title: "PinAttachmentParams",
172318
- description: "Parameters for pinning/unpinning an attachment"
172319
- });
172320
- var DownloadAttachmentParamsSchema = Schema_exports.Struct({
172321
- attachmentId: AttachmentId.annotations({
172322
- description: "Attachment ID"
172323
- })
172324
- }).annotations({
172325
- title: "DownloadAttachmentParams",
172326
- description: "Parameters for getting attachment download URL"
172327
- });
172328
- var AddIssueAttachmentParamsBase = Schema_exports.Struct({
172329
- project: ProjectIdentifier.annotations({
172330
- description: "Project identifier (e.g., 'HULY')"
172331
- }),
172332
- identifier: IssueIdentifier.annotations({
172333
- description: "Issue identifier (e.g., 'HULY-123')"
172334
- }),
172335
- ...FileSourceFields
172336
- });
172337
- var AddIssueAttachmentParamsSchema = AddIssueAttachmentParamsBase.pipe(
172338
- Schema_exports.filter(hasFileSource)
172339
- ).annotations({
172340
- title: "AddIssueAttachmentParams",
172341
- description: "Parameters for adding an attachment to an issue"
172342
- });
172343
- var AddDocumentAttachmentParamsBase = Schema_exports.Struct({
172344
- teamspace: TeamspaceIdentifier.annotations({
172345
- description: "Teamspace name or ID"
172346
- }),
172347
- document: DocumentIdentifier.annotations({
172348
- description: "Document title or ID"
172349
- }),
172350
- ...FileSourceFields
172167
+ ];
172168
+ const socialIdToName = yield* buildSocialIdToPersonNameMap(client, uniqueSocialIds);
172169
+ const summaries = messages.map((msg) => {
172170
+ const senderName = socialIdToName.get(msg.modifiedBy);
172171
+ return {
172172
+ id: MessageId.make(msg._id),
172173
+ body: markupToMarkdownString(msg.message, markupUrlConfig),
172174
+ sender: senderName !== void 0 ? PersonName.make(senderName) : void 0,
172175
+ senderId: msg.modifiedBy,
172176
+ createdOn: msg.createdOn,
172177
+ modifiedOn: msg.modifiedOn,
172178
+ editedOn: msg.editedOn,
172179
+ replies: msg.replies
172180
+ };
172181
+ });
172182
+ return { messages: summaries, total };
172351
172183
  });
172352
- var AddDocumentAttachmentParamsSchema = AddDocumentAttachmentParamsBase.pipe(
172353
- Schema_exports.filter(hasFileSource)
172354
- ).annotations({
172355
- title: "AddDocumentAttachmentParams",
172356
- description: "Parameters for adding an attachment to a document"
172184
+ var sendChannelMessage = (params) => Effect_exports.gen(function* () {
172185
+ const { channel, client } = yield* findChannel(params.channel);
172186
+ const markupUrlConfig = client.markupUrlConfig;
172187
+ const messageId = (0, import_core19.generateId)();
172188
+ const markup = markdownToMarkupString(params.body, markupUrlConfig);
172189
+ const messageData = {
172190
+ message: markup,
172191
+ attachments: 0
172192
+ };
172193
+ yield* client.addCollection(
172194
+ chunter.class.ChatMessage,
172195
+ channel._id,
172196
+ channel._id,
172197
+ chunter.class.Channel,
172198
+ "messages",
172199
+ messageData,
172200
+ messageId
172201
+ );
172202
+ return { id: MessageId.make(messageId), channelId: ChannelId.make(channel._id) };
172203
+ });
172204
+ var listDirectMessages = (params) => Effect_exports.gen(function* () {
172205
+ const client = yield* HulyClient;
172206
+ const limit = clampLimit(params.limit);
172207
+ const dms = yield* client.findAll(
172208
+ chunter.class.DirectMessage,
172209
+ { members: client.getAccountUuid() },
172210
+ {
172211
+ limit,
172212
+ sort: {
172213
+ modifiedOn: import_core19.SortingOrder.Descending
172214
+ }
172215
+ }
172216
+ );
172217
+ const total = dms.total;
172218
+ const uniqueAccountUuids = [
172219
+ ...new Set(
172220
+ dms.flatMap((dm) => dm.members)
172221
+ )
172222
+ ];
172223
+ const accountUuidToName = yield* buildAccountUuidToNameMap(client, uniqueAccountUuids);
172224
+ const summaries = dms.map((dm) => {
172225
+ const participants = dm.members.map((m) => accountUuidToName.get(m)).filter((n) => n !== void 0).map((n) => PersonName.make(n));
172226
+ const participantIds = dm.members.map((m) => AccountUuid.make(m));
172227
+ return {
172228
+ id: ChannelId.make(dm._id),
172229
+ participants,
172230
+ participantIds,
172231
+ messages: dm.messages,
172232
+ modifiedOn: dm.modifiedOn
172233
+ };
172234
+ });
172235
+ return { conversations: summaries, total };
172357
172236
  });
172358
- var listAttachmentsParamsJsonSchema = JSONSchema_exports.make(ListAttachmentsParamsSchema);
172359
- var getAttachmentParamsJsonSchema = JSONSchema_exports.make(GetAttachmentParamsSchema);
172360
- var addAttachmentParamsJsonSchema = JSONSchema_exports.make(AddAttachmentParamsSchema);
172361
- var updateAttachmentParamsJsonSchema = JSONSchema_exports.make(UpdateAttachmentParamsSchema);
172362
- var deleteAttachmentParamsJsonSchema = JSONSchema_exports.make(DeleteAttachmentParamsSchema);
172363
- var pinAttachmentParamsJsonSchema = JSONSchema_exports.make(PinAttachmentParamsSchema);
172364
- var downloadAttachmentParamsJsonSchema = JSONSchema_exports.make(DownloadAttachmentParamsSchema);
172365
- var addIssueAttachmentParamsJsonSchema = JSONSchema_exports.make(AddIssueAttachmentParamsSchema);
172366
- var addDocumentAttachmentParamsJsonSchema = JSONSchema_exports.make(AddDocumentAttachmentParamsSchema);
172367
- var parseListAttachmentsParams = Schema_exports.decodeUnknown(ListAttachmentsParamsSchema);
172368
- var parseGetAttachmentParams = Schema_exports.decodeUnknown(GetAttachmentParamsSchema);
172369
- var parseAddAttachmentParams = Schema_exports.decodeUnknown(AddAttachmentParamsSchema);
172370
- var parseUpdateAttachmentParams = Schema_exports.decodeUnknown(UpdateAttachmentParamsSchema);
172371
- var parseDeleteAttachmentParams = Schema_exports.decodeUnknown(DeleteAttachmentParamsSchema);
172372
- var parsePinAttachmentParams = Schema_exports.decodeUnknown(PinAttachmentParamsSchema);
172373
- var parseDownloadAttachmentParams = Schema_exports.decodeUnknown(DownloadAttachmentParamsSchema);
172374
- var parseAddIssueAttachmentParams = Schema_exports.decodeUnknown(AddIssueAttachmentParamsSchema);
172375
- var parseAddDocumentAttachmentParams = Schema_exports.decodeUnknown(AddDocumentAttachmentParamsSchema);
172376
-
172377
- // src/huly/operations/attachments.ts
172378
- var import_core23 = __toESM(require_lib4(), 1);
172379
172237
 
172380
172238
  // src/huly/operations/documents.ts
172381
- var import_core22 = __toESM(require_lib4(), 1);
172239
+ var import_core21 = __toESM(require_lib4(), 1);
172382
172240
  var import_rank = __toESM(require_lib33(), 1);
172383
172241
 
172384
172242
  // src/huly/operations/documents-edit.ts
@@ -172412,875 +172270,1141 @@ var editDocument = (params) => Effect_exports.gen(function* () {
172412
172270
  updateOps.content = contentMarkupRef;
172413
172271
  }
172414
172272
  }
172415
- if (params.old_text !== void 0 && params.new_text !== void 0) {
172416
- if (!doc.content) {
172417
- return yield* new DocumentEmptyContentError({ identifier: params.document });
172418
- }
172419
- const currentContent = yield* client.fetchMarkup(
172420
- doc._class,
172421
- doc._id,
172422
- "content",
172423
- doc.content,
172424
- "markdown"
172425
- );
172426
- const occurrences = countOccurrences(currentContent, params.old_text);
172427
- if (occurrences === 0) {
172428
- return yield* new DocumentTextNotFoundError({ searchText: params.old_text });
172429
- }
172430
- if (occurrences > 1 && !params.replace_all) {
172431
- return yield* new DocumentTextMultipleMatchesError({
172432
- searchText: params.old_text,
172433
- matchCount: occurrences
172434
- });
172435
- }
172436
- const idx = currentContent.indexOf(params.old_text);
172437
- 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);
172438
- yield* client.updateMarkup(
172439
- documentPlugin.class.Document,
172440
- doc._id,
172441
- "content",
172442
- newContent,
172443
- "markdown"
172444
- );
172445
- contentUpdatedInPlace = true;
172273
+ if (params.old_text !== void 0 && params.new_text !== void 0) {
172274
+ if (!doc.content) {
172275
+ return yield* new DocumentEmptyContentError({ identifier: params.document });
172276
+ }
172277
+ const currentContent = yield* client.fetchMarkup(
172278
+ doc._class,
172279
+ doc._id,
172280
+ "content",
172281
+ doc.content,
172282
+ "markdown"
172283
+ );
172284
+ const occurrences = countOccurrences(currentContent, params.old_text);
172285
+ if (occurrences === 0) {
172286
+ return yield* new DocumentTextNotFoundError({ searchText: params.old_text });
172287
+ }
172288
+ if (occurrences > 1 && !params.replace_all) {
172289
+ return yield* new DocumentTextMultipleMatchesError({
172290
+ searchText: params.old_text,
172291
+ matchCount: occurrences
172292
+ });
172293
+ }
172294
+ const idx = currentContent.indexOf(params.old_text);
172295
+ 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);
172296
+ yield* client.updateMarkup(
172297
+ documentPlugin.class.Document,
172298
+ doc._id,
172299
+ "content",
172300
+ newContent,
172301
+ "markdown"
172302
+ );
172303
+ contentUpdatedInPlace = true;
172304
+ }
172305
+ const finalTitle = updateOps.title ?? doc.title;
172306
+ const url4 = buildDocumentUrlFromConfig(client.workbenchUrlConfig, finalTitle, DocumentId.make(doc._id));
172307
+ if (Object.keys(updateOps).length === 0 && !contentUpdatedInPlace) {
172308
+ return { id: DocumentId.make(doc._id), updated: false, url: url4 };
172309
+ }
172310
+ if (Object.keys(updateOps).length > 0) {
172311
+ yield* client.updateDoc(
172312
+ documentPlugin.class.Document,
172313
+ teamspace._id,
172314
+ doc._id,
172315
+ updateOps
172316
+ );
172317
+ }
172318
+ return { id: DocumentId.make(doc._id), updated: true, url: url4 };
172319
+ });
172320
+ var countOccurrences = (text, search) => {
172321
+ let count3 = 0;
172322
+ let pos = text.indexOf(search);
172323
+ while (pos !== -1) {
172324
+ count3++;
172325
+ pos = text.indexOf(search, pos + search.length);
172326
+ }
172327
+ return count3;
172328
+ };
172329
+
172330
+ // src/huly/operations/documents-inline-comments.ts
172331
+ var import_core20 = __toESM(require_lib4(), 1);
172332
+ var import_text3 = __toESM(require_lib9(), 1);
172333
+ var INLINE_COMMENT_MARK_TYPE = "inline-comment";
172334
+ var extractInlineComments = (root) => {
172335
+ const threadMap = /* @__PURE__ */ new Map();
172336
+ (0, import_text3.traverseAllMarks)(root, (textNode, mark) => {
172337
+ if (String(mark.type) !== INLINE_COMMENT_MARK_TYPE) return;
172338
+ const threadId = mark.attrs?.thread;
172339
+ if (typeof threadId !== "string" || threadId === "") return;
172340
+ const text = textNode.text ?? "";
172341
+ if (!threadMap.has(threadId)) {
172342
+ threadMap.set(threadId, []);
172343
+ }
172344
+ threadMap.get(threadId)?.push(text);
172345
+ });
172346
+ return [...threadMap.entries()].map(([threadId, textFragments]) => ({
172347
+ threadId,
172348
+ textFragments
172349
+ }));
172350
+ };
172351
+ var listInlineComments = (params) => Effect_exports.gen(function* () {
172352
+ const { client, doc } = yield* findTeamspaceAndDocument({
172353
+ teamspace: params.teamspace,
172354
+ document: params.document
172355
+ });
172356
+ const markupUrlConfig = client.markupUrlConfig;
172357
+ if (!doc.content) {
172358
+ return { comments: [], total: 0 };
172359
+ }
172360
+ const rawMarkup = yield* client.fetchMarkup(
172361
+ doc._class,
172362
+ doc._id,
172363
+ "content",
172364
+ doc.content,
172365
+ "markup"
172366
+ );
172367
+ const root = (0, import_text3.markupToJSON)(rawMarkup);
172368
+ const extracted = extractInlineComments(root);
172369
+ if (extracted.length === 0) {
172370
+ return { comments: [], total: 0 };
172371
+ }
172372
+ let nameMap = /* @__PURE__ */ new Map();
172373
+ const threadRepliesMap = /* @__PURE__ */ new Map();
172374
+ if (params.includeReplies) {
172375
+ const threadIds = extracted.map((c) => toRef(c.threadId));
172376
+ const allReplies = yield* client.findAll(
172377
+ chunter.class.ThreadMessage,
172378
+ { attachedTo: { $in: threadIds } },
172379
+ { sort: { createdOn: import_core20.SortingOrder.Ascending } }
172380
+ );
172381
+ for (const r of allReplies) {
172382
+ const key = r.attachedTo;
172383
+ if (!threadRepliesMap.has(key)) {
172384
+ threadRepliesMap.set(key, []);
172385
+ }
172386
+ threadRepliesMap.get(key)?.push(r);
172387
+ }
172388
+ const senderIds = [
172389
+ ...new Set(
172390
+ allReplies.map((r) => r.createdBy).filter((id) => id !== void 0)
172391
+ )
172392
+ ];
172393
+ nameMap = yield* buildSocialIdToPersonNameMap(client, senderIds);
172394
+ }
172395
+ const comments = extracted.map((comment) => {
172396
+ const thread = {
172397
+ threadId: comment.threadId,
172398
+ text: comment.textFragments.join("")
172399
+ };
172400
+ if (params.includeReplies) {
172401
+ const threadReplies = threadRepliesMap.get(comment.threadId) ?? [];
172402
+ const replies = threadReplies.map((r) => ({
172403
+ id: r._id,
172404
+ body: optionalMarkupToMarkdown(r.message, markupUrlConfig, ""),
172405
+ sender: r.createdBy !== void 0 ? nameMap.get(r.createdBy) : void 0,
172406
+ createdOn: r.createdOn
172407
+ }));
172408
+ return { ...thread, replies };
172409
+ }
172410
+ return thread;
172411
+ });
172412
+ return { comments, total: comments.length };
172413
+ });
172414
+
172415
+ // src/huly/operations/documents.ts
172416
+ var findTeamspace = (identifier2, opts) => Effect_exports.gen(function* () {
172417
+ const client = yield* HulyClient;
172418
+ const nameQuery = { name: identifier2 };
172419
+ const idQuery = { _id: toRef(identifier2) };
172420
+ if (!opts?.includeArchived) {
172421
+ nameQuery.archived = false;
172422
+ idQuery.archived = false;
172423
+ }
172424
+ const teamspace = yield* findByNameOrId(
172425
+ client,
172426
+ documentPlugin.class.Teamspace,
172427
+ nameQuery,
172428
+ idQuery
172429
+ );
172430
+ if (teamspace === void 0) {
172431
+ return yield* new TeamspaceNotFoundError({ identifier: identifier2 });
172432
+ }
172433
+ return { client, teamspace };
172434
+ });
172435
+ var findTeamspaceAndDocument = (params) => Effect_exports.gen(function* () {
172436
+ const { client, teamspace } = yield* findTeamspace(params.teamspace);
172437
+ const doc = yield* findByNameOrId(
172438
+ client,
172439
+ documentPlugin.class.Document,
172440
+ { space: teamspace._id, title: params.document },
172441
+ { space: teamspace._id, _id: toRef(params.document) }
172442
+ );
172443
+ if (doc === void 0) {
172444
+ return yield* new DocumentNotFoundError({
172445
+ identifier: params.document,
172446
+ teamspace: params.teamspace
172447
+ });
172448
+ }
172449
+ return { client, teamspace, doc };
172450
+ });
172451
+ var listTeamspaces = (params) => Effect_exports.gen(function* () {
172452
+ const client = yield* HulyClient;
172453
+ const query = {};
172454
+ if (!params.includeArchived) {
172455
+ query.archived = false;
172456
+ }
172457
+ const limit = clampLimit(params.limit);
172458
+ const teamspaces = yield* client.findAll(
172459
+ documentPlugin.class.Teamspace,
172460
+ query,
172461
+ {
172462
+ limit,
172463
+ sort: {
172464
+ name: import_core21.SortingOrder.Ascending
172465
+ }
172466
+ }
172467
+ );
172468
+ const total = teamspaces.total;
172469
+ const summaries = teamspaces.map((ts) => ({
172470
+ id: TeamspaceId.make(ts._id),
172471
+ name: ts.name,
172472
+ description: ts.description || void 0,
172473
+ archived: ts.archived,
172474
+ private: ts.private
172475
+ }));
172476
+ return {
172477
+ teamspaces: summaries,
172478
+ total
172479
+ };
172480
+ });
172481
+ var getTeamspace = (params) => Effect_exports.gen(function* () {
172482
+ const { client, teamspace } = yield* findTeamspace(params.teamspace, { includeArchived: true });
172483
+ const docs = yield* client.findAll(
172484
+ documentPlugin.class.Document,
172485
+ { space: teamspace._id },
172486
+ { limit: 1, total: true }
172487
+ );
172488
+ return {
172489
+ id: TeamspaceId.make(teamspace._id),
172490
+ name: teamspace.name,
172491
+ description: teamspace.description || void 0,
172492
+ archived: teamspace.archived,
172493
+ private: teamspace.private,
172494
+ documents: docs.total
172495
+ };
172496
+ });
172497
+ var createTeamspace = (params) => Effect_exports.gen(function* () {
172498
+ const client = yield* HulyClient;
172499
+ const existing = yield* client.findOne(
172500
+ documentPlugin.class.Teamspace,
172501
+ { name: params.name, archived: false }
172502
+ );
172503
+ if (existing !== void 0) {
172504
+ return {
172505
+ id: TeamspaceId.make(existing._id),
172506
+ name: existing.name,
172507
+ created: false
172508
+ };
172509
+ }
172510
+ const teamspaceId = (0, import_core21.generateId)();
172511
+ const teamspaceData = {
172512
+ name: params.name,
172513
+ description: params.description ?? "",
172514
+ private: params.private ?? false,
172515
+ archived: false,
172516
+ members: [client.getAccountUuid()],
172517
+ owners: [client.getAccountUuid()],
172518
+ icon: documentPlugin.icon.Teamspace,
172519
+ type: documentPlugin.spaceType.DefaultTeamspaceType
172520
+ };
172521
+ yield* client.createDoc(
172522
+ documentPlugin.class.Teamspace,
172523
+ core.space.Space,
172524
+ teamspaceData,
172525
+ teamspaceId
172526
+ );
172527
+ return {
172528
+ id: TeamspaceId.make(teamspaceId),
172529
+ name: params.name,
172530
+ created: true
172531
+ };
172532
+ });
172533
+ var updateTeamspace = (params) => Effect_exports.gen(function* () {
172534
+ const { client, teamspace } = yield* findTeamspace(params.teamspace, { includeArchived: true });
172535
+ const updateOps = {};
172536
+ if (params.name !== void 0) {
172537
+ updateOps.name = params.name;
172538
+ }
172539
+ if (params.description !== void 0) {
172540
+ updateOps.description = params.description === null ? "" : params.description;
172446
172541
  }
172447
- const finalTitle = updateOps.title ?? doc.title;
172448
- const url4 = buildDocumentUrlFromConfig(client.workbenchUrlConfig, finalTitle, DocumentId.make(doc._id));
172449
- if (Object.keys(updateOps).length === 0 && !contentUpdatedInPlace) {
172450
- return { id: DocumentId.make(doc._id), updated: false, url: url4 };
172542
+ if (params.archived !== void 0) {
172543
+ updateOps.archived = params.archived;
172451
172544
  }
172452
- if (Object.keys(updateOps).length > 0) {
172453
- yield* client.updateDoc(
172454
- documentPlugin.class.Document,
172455
- teamspace._id,
172456
- doc._id,
172457
- updateOps
172458
- );
172545
+ if (Object.keys(updateOps).length === 0) {
172546
+ return { id: TeamspaceId.make(teamspace._id), updated: false };
172459
172547
  }
172460
- return { id: DocumentId.make(doc._id), updated: true, url: url4 };
172548
+ yield* client.updateDoc(
172549
+ documentPlugin.class.Teamspace,
172550
+ core.space.Space,
172551
+ teamspace._id,
172552
+ updateOps
172553
+ );
172554
+ return { id: TeamspaceId.make(teamspace._id), updated: true };
172461
172555
  });
172462
- var countOccurrences = (text, search) => {
172463
- let count3 = 0;
172464
- let pos = text.indexOf(search);
172465
- while (pos !== -1) {
172466
- count3++;
172467
- pos = text.indexOf(search, pos + search.length);
172556
+ var deleteTeamspace = (params) => Effect_exports.gen(function* () {
172557
+ const { client, teamspace } = yield* findTeamspace(params.teamspace, { includeArchived: true });
172558
+ yield* client.removeDoc(
172559
+ documentPlugin.class.Teamspace,
172560
+ core.space.Space,
172561
+ teamspace._id
172562
+ );
172563
+ return { id: TeamspaceId.make(teamspace._id), deleted: true };
172564
+ });
172565
+ var listDocuments = (params) => Effect_exports.gen(function* () {
172566
+ const { client, teamspace } = yield* findTeamspace(params.teamspace);
172567
+ const limit = clampLimit(params.limit);
172568
+ const query = {
172569
+ space: teamspace._id
172570
+ };
172571
+ if (params.titleSearch !== void 0 && params.titleSearch.trim() !== "") {
172572
+ query.title = { $like: `%${escapeLikeWildcards(params.titleSearch)}%` };
172468
172573
  }
172469
- return count3;
172470
- };
172471
-
172472
- // src/huly/operations/documents-inline-comments.ts
172473
- var import_core21 = __toESM(require_lib4(), 1);
172474
- var import_text3 = __toESM(require_lib9(), 1);
172475
-
172476
- // src/huly/operations/channels.ts
172477
- var import_core20 = __toESM(require_lib4(), 1);
172478
-
172479
- // src/huly/operations/channel-messages-shared.ts
172480
- var findChannelMessage = (params) => Effect_exports.gen(function* () {
172481
- const { channel, client } = yield* findChannel(params.channel);
172482
- const message = yield* client.findOne(
172483
- chunter.class.ChatMessage,
172574
+ if (params.titleRegex !== void 0 && params.titleRegex.trim() !== "") {
172575
+ query.title = { $regex: params.titleRegex };
172576
+ }
172577
+ if (params.contentSearch !== void 0 && params.contentSearch.trim() !== "") {
172578
+ query.$search = params.contentSearch;
172579
+ }
172580
+ const documents = yield* client.findAll(
172581
+ documentPlugin.class.Document,
172582
+ query,
172484
172583
  {
172485
- _id: toRef(params.messageId),
172486
- space: channel._id
172584
+ limit,
172585
+ sort: {
172586
+ modifiedOn: import_core21.SortingOrder.Descending
172587
+ }
172487
172588
  }
172488
172589
  );
172489
- if (message === void 0) {
172490
- return yield* new MessageNotFoundError({
172491
- messageId: params.messageId,
172492
- channel: params.channel
172493
- });
172494
- }
172495
- return { client, channel, message };
172590
+ const total = documents.total;
172591
+ const summaries = documents.map((doc) => ({
172592
+ id: DocumentId.make(doc._id),
172593
+ title: doc.title,
172594
+ teamspace: teamspace.name,
172595
+ url: buildDocumentUrlFromConfig(client.workbenchUrlConfig, doc.title, DocumentId.make(doc._id)),
172596
+ modifiedOn: doc.modifiedOn
172597
+ }));
172598
+ return {
172599
+ documents: summaries,
172600
+ total
172601
+ };
172496
172602
  });
172497
-
172498
- // src/huly/operations/channels-messages.ts
172499
- var updateChannelMessage = (params) => Effect_exports.gen(function* () {
172500
- const { channel, client, message } = yield* findChannelMessage(params);
172501
- const markupUrlConfig = client.markupUrlConfig;
172502
- const markup = markdownToMarkupString(params.body, markupUrlConfig);
172503
- const now2 = yield* Clock_exports.currentTimeMillis;
172504
- const updateOps = {
172505
- message: markup,
172506
- editedOn: now2
172603
+ var getDocument = (params) => Effect_exports.gen(function* () {
172604
+ const { client, doc, teamspace } = yield* findTeamspaceAndDocument({
172605
+ teamspace: params.teamspace,
172606
+ document: params.document
172607
+ });
172608
+ const content = doc.content ? yield* client.fetchMarkup(
172609
+ doc._class,
172610
+ doc._id,
172611
+ "content",
172612
+ doc.content,
172613
+ "markdown"
172614
+ ) : void 0;
172615
+ const result = {
172616
+ id: DocumentId.make(doc._id),
172617
+ title: doc.title,
172618
+ content,
172619
+ teamspace: teamspace.name,
172620
+ url: buildDocumentUrlFromConfig(client.workbenchUrlConfig, doc.title, DocumentId.make(doc._id)),
172621
+ modifiedOn: doc.modifiedOn,
172622
+ createdOn: doc.createdOn
172507
172623
  };
172508
- yield* client.updateDoc(
172509
- chunter.class.ChatMessage,
172510
- channel._id,
172511
- message._id,
172512
- updateOps
172624
+ return result;
172625
+ });
172626
+ var createDocument = (params) => Effect_exports.gen(function* () {
172627
+ const { client, teamspace } = yield* findTeamspace(params.teamspace);
172628
+ const documentId = (0, import_core21.generateId)();
172629
+ const parent = params.parent;
172630
+ const parentRef = parent === void 0 ? documentPlugin.ids.NoParent : yield* Effect_exports.gen(function* () {
172631
+ const parentDoc = yield* findByNameOrId(
172632
+ client,
172633
+ documentPlugin.class.Document,
172634
+ { space: teamspace._id, title: parent },
172635
+ { space: teamspace._id, _id: toRef(parent) }
172636
+ );
172637
+ if (parentDoc === void 0) {
172638
+ return yield* new DocumentNotFoundError({
172639
+ identifier: parent,
172640
+ teamspace: params.teamspace
172641
+ });
172642
+ }
172643
+ return parentDoc._id;
172644
+ });
172645
+ const lastDoc = yield* client.findOne(
172646
+ documentPlugin.class.Document,
172647
+ { space: teamspace._id },
172648
+ { sort: { rank: import_core21.SortingOrder.Descending } }
172513
172649
  );
172514
- return { id: MessageId.make(message._id), updated: true };
172650
+ const rank = (0, import_rank.makeRank)(lastDoc?.rank, void 0);
172651
+ const contentMarkupRef = params.content !== void 0 && params.content.trim() !== "" ? yield* client.uploadMarkup(
172652
+ documentPlugin.class.Document,
172653
+ documentId,
172654
+ "content",
172655
+ params.content,
172656
+ "markdown"
172657
+ ) : null;
172658
+ const documentData = {
172659
+ title: params.title,
172660
+ content: contentMarkupRef,
172661
+ parent: parentRef,
172662
+ rank
172663
+ };
172664
+ yield* client.createDoc(
172665
+ documentPlugin.class.Document,
172666
+ teamspace._id,
172667
+ documentData,
172668
+ documentId
172669
+ );
172670
+ return {
172671
+ id: DocumentId.make(documentId),
172672
+ title: params.title,
172673
+ url: buildDocumentUrlFromConfig(client.workbenchUrlConfig, params.title, DocumentId.make(documentId))
172674
+ };
172515
172675
  });
172516
- var deleteChannelMessage = (params) => Effect_exports.gen(function* () {
172517
- const { channel, client, message } = yield* findChannelMessage(params);
172676
+ var deleteDocument = (params) => Effect_exports.gen(function* () {
172677
+ const { client, doc, teamspace } = yield* findTeamspaceAndDocument(params);
172518
172678
  yield* client.removeDoc(
172519
- chunter.class.ChatMessage,
172520
- channel._id,
172521
- message._id
172679
+ documentPlugin.class.Document,
172680
+ teamspace._id,
172681
+ doc._id
172522
172682
  );
172523
- return { id: MessageId.make(message._id), deleted: true };
172683
+ return { id: DocumentId.make(doc._id), deleted: true };
172524
172684
  });
172525
172685
 
172526
- // src/huly/operations/channels.ts
172527
- var personIdsAsSocialIdentityRefs = (ids3) => ids3;
172528
- var findChannel = (identifier2) => Effect_exports.gen(function* () {
172686
+ // src/huly/operations/issues-shared.ts
172687
+ var import_tracker = __toESM(require_lib36(), 1);
172688
+
172689
+ // src/utils/normalize.ts
172690
+ var normalizeForComparison = (s) => s.replace(/[-_ ]/g, "").toLowerCase();
172691
+
172692
+ // src/huly/operations/issues-shared.ts
172693
+ var zeroAsUnset = (value3) => value3 > 0 ? PositiveNumber.make(value3) : void 0;
172694
+ var findProject = (projectIdentifier) => Effect_exports.gen(function* () {
172529
172695
  const client = yield* HulyClient;
172530
- const channel = yield* findByNameOrId(
172531
- client,
172532
- chunter.class.Channel,
172533
- { name: identifier2 },
172534
- { _id: toRef(identifier2) }
172696
+ const project3 = yield* findOneOrFail(
172697
+ client,
172698
+ tracker.class.Project,
172699
+ { identifier: projectIdentifier },
172700
+ () => new ProjectNotFoundError({ identifier: projectIdentifier })
172535
172701
  );
172536
- if (channel === void 0) {
172537
- return yield* new ChannelNotFoundError({ identifier: identifier2 });
172538
- }
172539
- return { client, channel };
172702
+ return { client, project: project3 };
172540
172703
  });
172541
- var buildSocialIdToPersonNameMap = (client, socialIds) => Effect_exports.gen(function* () {
172542
- if (socialIds.length === 0) {
172543
- return /* @__PURE__ */ new Map();
172544
- }
172545
- const socialIdentities = yield* client.findAll(
172546
- contact.class.SocialIdentity,
172547
- { _id: { $in: personIdsAsSocialIdentityRefs(socialIds) } }
172548
- );
172549
- if (socialIdentities.length === 0) {
172550
- return /* @__PURE__ */ new Map();
172551
- }
172552
- const personRefs = [...new Set(socialIdentities.map((si) => si.attachedTo))];
172553
- const persons = yield* client.findAll(
172554
- contact.class.Person,
172555
- { _id: { $in: personRefs } }
172704
+ var findProjectWithStatuses = (projectIdentifier) => Effect_exports.gen(function* () {
172705
+ const client = yield* HulyClient;
172706
+ const project3 = yield* findOneOrFail(
172707
+ client,
172708
+ tracker.class.Project,
172709
+ { identifier: projectIdentifier },
172710
+ () => new ProjectNotFoundError({ identifier: projectIdentifier }),
172711
+ { lookup: { type: task.class.ProjectType } }
172556
172712
  );
172557
- const personById = new Map(persons.map((p) => [p._id, p]));
172558
- const result = /* @__PURE__ */ new Map();
172559
- for (const si of socialIdentities) {
172560
- const person = personById.get(si.attachedTo);
172561
- if (person !== void 0) {
172562
- result.set(si._id, person.name);
172713
+ const projectType = project3.$lookup?.type;
172714
+ const statuses = [];
172715
+ if (projectType?.statuses) {
172716
+ const statusRefs = projectType.statuses.map((s) => s._id);
172717
+ if (statusRefs.length > 0) {
172718
+ const statusDocsResult = yield* Effect_exports.either(
172719
+ client.findAll(
172720
+ core.class.Status,
172721
+ { _id: { $in: statusRefs } }
172722
+ )
172723
+ );
172724
+ if (statusDocsResult._tag === "Right") {
172725
+ for (const doc of statusDocsResult.right) {
172726
+ const categoryStr = doc.category ? doc.category : "";
172727
+ statuses.push({
172728
+ _id: doc._id,
172729
+ name: doc.name,
172730
+ isDone: categoryStr === task.statusCategory.Won,
172731
+ isCanceled: categoryStr === task.statusCategory.Lost
172732
+ });
172733
+ }
172734
+ } else {
172735
+ yield* Effect_exports.logWarning(
172736
+ `Status query failed for project ${projectIdentifier}, using fallback. Category-based filtering (open/done/canceled) will use name heuristics. Error: ${statusDocsResult.left.message}`
172737
+ );
172738
+ for (const ps of projectType.statuses) {
172739
+ const name = ps._id.split(":").pop() ?? "Unknown";
172740
+ const nameLower = name.toLowerCase();
172741
+ const isDone5 = nameLower.includes("done") || nameLower.includes("complete") || nameLower.includes("finished") || nameLower.includes("resolved") || nameLower.includes("closed");
172742
+ const isCanceled = nameLower.includes("cancel") || nameLower.includes("reject") || nameLower.includes("abort") || nameLower.includes("wontfix") || nameLower.includes("invalid");
172743
+ statuses.push({
172744
+ _id: ps._id,
172745
+ name,
172746
+ isDone: isDone5,
172747
+ isCanceled
172748
+ });
172749
+ }
172750
+ }
172563
172751
  }
172564
172752
  }
172565
- return result;
172753
+ const defaultStatusId = project3.defaultIssueStatus || statuses[0]?._id;
172754
+ return { client, project: project3, statuses, defaultStatusId };
172566
172755
  });
172567
- var buildAccountUuidToNameMap = (client, accountUuids) => Effect_exports.gen(function* () {
172568
- if (accountUuids.length === 0) {
172569
- return /* @__PURE__ */ new Map();
172756
+ var parseIssueIdentifier = (identifier2, projectIdentifier) => {
172757
+ const idStr = String(identifier2).trim();
172758
+ const match16 = idStr.match(/^([A-Z]+)-(\d+)$/i);
172759
+ if (match16) {
172760
+ return {
172761
+ fullIdentifier: `${match16[1].toUpperCase()}-${match16[2]}`,
172762
+ number: parseInt(match16[2], 10)
172763
+ };
172570
172764
  }
172571
- const employees = yield* client.findAll(
172572
- contact.mixin.Employee,
172573
- { personUuid: { $in: accountUuids } }
172765
+ const numMatch = idStr.match(/^\d+$/);
172766
+ if (numMatch) {
172767
+ const num = parseInt(idStr, 10);
172768
+ return {
172769
+ fullIdentifier: `${projectIdentifier.toUpperCase()}-${num}`,
172770
+ number: num
172771
+ };
172772
+ }
172773
+ return { fullIdentifier: idStr, number: null };
172774
+ };
172775
+ var findIssueInProject = (client, project3, identifierStr) => Effect_exports.gen(function* () {
172776
+ const { fullIdentifier, number: number8 } = parseIssueIdentifier(
172777
+ identifierStr,
172778
+ project3.identifier
172574
172779
  );
172575
- const result = /* @__PURE__ */ new Map();
172576
- for (const emp of employees) {
172577
- if (emp.personUuid !== void 0) {
172578
- result.set(emp.personUuid, emp.name);
172780
+ const issue2 = (yield* client.findOne(
172781
+ tracker.class.Issue,
172782
+ {
172783
+ space: project3._id,
172784
+ identifier: fullIdentifier
172579
172785
  }
172580
- }
172581
- return result;
172582
- });
172583
- var listChannels = (params) => Effect_exports.gen(function* () {
172584
- const client = yield* HulyClient;
172585
- const query = {};
172586
- if (!params.includeArchived) {
172587
- query.archived = false;
172588
- }
172589
- if (params.nameSearch !== void 0 && params.nameSearch.trim() !== "") {
172590
- query.name = { $like: `%${escapeLikeWildcards(params.nameSearch)}%` };
172591
- }
172592
- if (params.nameRegex !== void 0 && params.nameRegex.trim() !== "") {
172593
- query.name = { $regex: params.nameRegex };
172594
- }
172595
- if (params.topicSearch !== void 0 && params.topicSearch.trim() !== "") {
172596
- query.topic = { $like: `%${escapeLikeWildcards(params.topicSearch)}%` };
172597
- }
172598
- const limit = clampLimit(params.limit);
172599
- const channels = yield* client.findAll(
172600
- chunter.class.Channel,
172601
- query,
172786
+ )) ?? (number8 !== null ? yield* client.findOne(
172787
+ tracker.class.Issue,
172602
172788
  {
172603
- limit,
172604
- sort: {
172605
- name: import_core20.SortingOrder.Ascending
172606
- }
172789
+ space: project3._id,
172790
+ number: number8
172607
172791
  }
172608
- );
172609
- const summaries = channels.map((ch) => ({
172610
- id: ChannelId.make(ch._id),
172611
- name: ChannelName.make(ch.name),
172612
- topic: ch.topic || void 0,
172613
- private: ch.private,
172614
- archived: ch.archived,
172615
- members: ch.members.length,
172616
- messages: ch.messages,
172617
- modifiedOn: ch.modifiedOn
172618
- }));
172619
- return summaries;
172792
+ ) : void 0);
172793
+ if (issue2 === void 0) {
172794
+ return yield* new IssueNotFoundError({
172795
+ identifier: identifierStr,
172796
+ project: project3.identifier
172797
+ });
172798
+ }
172799
+ return issue2;
172620
172800
  });
172621
- var getChannel = (params) => Effect_exports.gen(function* () {
172622
- const { channel, client } = yield* findChannel(params.channel);
172623
- const memberNames = channel.members.length > 0 ? yield* Effect_exports.gen(function* () {
172624
- const accountUuidToName = yield* buildAccountUuidToNameMap(client, channel.members);
172625
- return channel.members.map((m) => accountUuidToName.get(m)).filter((n) => n !== void 0);
172626
- }) : void 0;
172627
- const result = {
172628
- id: ChannelId.make(channel._id),
172629
- name: ChannelName.make(channel.name),
172630
- topic: channel.topic || void 0,
172631
- description: channel.description || void 0,
172632
- private: channel.private,
172633
- archived: channel.archived,
172634
- members: memberNames?.map((m) => PersonName.make(m)),
172635
- messages: channel.messages,
172636
- modifiedOn: channel.modifiedOn,
172637
- createdOn: channel.createdOn
172638
- };
172639
- return result;
172801
+ var findProjectAndIssue = (params) => Effect_exports.gen(function* () {
172802
+ const { client, project: project3 } = yield* findProject(params.project);
172803
+ const issue2 = yield* findIssueInProject(client, project3, params.identifier);
172804
+ return { client, project: project3, issue: issue2 };
172640
172805
  });
172641
- var createChannel = (params) => Effect_exports.gen(function* () {
172642
- const client = yield* HulyClient;
172643
- const channelId = (0, import_core20.generateId)();
172644
- const channelData = {
172645
- name: params.name,
172646
- topic: params.topic || "",
172647
- description: "",
172648
- private: params.private ?? false,
172649
- archived: false,
172650
- members: [client.getAccountUuid()],
172651
- owners: [client.getAccountUuid()]
172652
- };
172653
- yield* client.createDoc(
172654
- chunter.class.Channel,
172655
- toRef(channelId),
172656
- channelData,
172657
- channelId
172806
+ var priorityToStringMap = {
172807
+ [import_tracker.IssuePriority.Urgent]: "urgent",
172808
+ [import_tracker.IssuePriority.High]: "high",
172809
+ [import_tracker.IssuePriority.Medium]: "medium",
172810
+ [import_tracker.IssuePriority.Low]: "low",
172811
+ [import_tracker.IssuePriority.NoPriority]: "no-priority"
172812
+ };
172813
+ var priorityToString = (priority) => priorityToStringMap[priority];
172814
+ var stringToPriorityMap = {
172815
+ "urgent": import_tracker.IssuePriority.Urgent,
172816
+ "high": import_tracker.IssuePriority.High,
172817
+ "medium": import_tracker.IssuePriority.Medium,
172818
+ "low": import_tracker.IssuePriority.Low,
172819
+ "no-priority": import_tracker.IssuePriority.NoPriority
172820
+ };
172821
+ var stringToPriority = (priority) => stringToPriorityMap[priority];
172822
+ var resolveStatusByName = (statuses, statusName, project3) => {
172823
+ const normalizedInput = normalizeForComparison(statusName);
172824
+ const matchingStatus = statuses.find(
172825
+ (s) => normalizeForComparison(s.name) === normalizedInput
172658
172826
  );
172659
- return { id: ChannelId.make(channelId), name: ChannelName.make(params.name) };
172660
- });
172661
- var updateChannel = (params) => Effect_exports.gen(function* () {
172662
- const { channel, client } = yield* findChannel(params.channel);
172663
- const updateOps = {};
172664
- if (params.name !== void 0) {
172665
- updateOps.name = params.name;
172666
- }
172667
- if (params.topic !== void 0) {
172668
- updateOps.topic = params.topic;
172669
- }
172670
- if (Object.keys(updateOps).length === 0) {
172671
- return { id: ChannelId.make(channel._id), updated: false };
172827
+ if (matchingStatus === void 0) {
172828
+ return Effect_exports.fail(new InvalidStatusError({ status: statusName, project: project3 }));
172672
172829
  }
172673
- yield* client.updateDoc(
172674
- chunter.class.Channel,
172675
- toRef(channel._id),
172676
- channel._id,
172677
- updateOps
172678
- );
172679
- return { id: ChannelId.make(channel._id), updated: true };
172830
+ return Effect_exports.succeed(matchingStatus._id);
172831
+ };
172832
+
172833
+ // src/huly/operations/activity.ts
172834
+ var optionalTimestamp = (value3) => value3 === void 0 ? void 0 : Timestamp.make(value3);
172835
+ var optionalNullableTimestamp = (value3) => value3 === void 0 || value3 === null ? value3 : Timestamp.make(value3);
172836
+ var optionalActivityCount = (value3) => value3 === void 0 ? void 0 : ActivityCount.make(value3);
172837
+ var optionalPersonId = (value3) => value3 === void 0 || value3 === "" ? void 0 : PersonId.make(value3);
172838
+ var activityTarget = (client, objectId, objectClass) => ({
172839
+ client,
172840
+ objectId: NonEmptyString2.make(objectId),
172841
+ objectClass: ObjectClassName.make(objectClass)
172680
172842
  });
172681
- var deleteChannel = (params) => Effect_exports.gen(function* () {
172682
- const { channel, client } = yield* findChannel(params.channel);
172683
- yield* client.removeDoc(
172684
- chunter.class.Channel,
172685
- toRef(channel._id),
172686
- channel._id
172843
+ var resolveActivityTarget = (params) => Effect_exports.gen(function* () {
172844
+ if (params.objectId !== void 0 && params.objectClass !== void 0) {
172845
+ const client = yield* HulyClient;
172846
+ return activityTarget(client, params.objectId, params.objectClass);
172847
+ }
172848
+ if (params.project !== void 0 && params.issueIdentifier !== void 0) {
172849
+ const { client, issue: issue2 } = yield* findProjectAndIssue({
172850
+ project: params.project,
172851
+ identifier: params.issueIdentifier
172852
+ });
172853
+ return activityTarget(client, issue2._id, tracker.class.Issue);
172854
+ }
172855
+ if (params.teamspace !== void 0 && params.document !== void 0) {
172856
+ const { client, doc } = yield* findTeamspaceAndDocument({
172857
+ teamspace: params.teamspace,
172858
+ document: params.document
172859
+ });
172860
+ return activityTarget(client, doc._id, documentPlugin.class.Document);
172861
+ }
172862
+ if (params.channel !== void 0) {
172863
+ const { channel, client } = yield* findChannel(params.channel);
172864
+ return activityTarget(client, channel._id, chunter.class.Channel);
172865
+ }
172866
+ return yield* Effect_exports.dieMessage(
172867
+ "Invalid list_activity parameters: choose objectId+objectClass, project+issueIdentifier, teamspace+document, or channel."
172687
172868
  );
172688
- return { id: ChannelId.make(channel._id), deleted: true };
172689
172869
  });
172690
- var listChannelMessages = (params) => Effect_exports.gen(function* () {
172691
- const { channel, client } = yield* findChannel(params.channel);
172692
- const markupUrlConfig = client.markupUrlConfig;
172870
+ var serverPopulatedCreateBy = "";
172871
+ var listActivity = (params) => Effect_exports.gen(function* () {
172872
+ const target = yield* resolveActivityTarget(params);
172693
172873
  const limit = clampLimit(params.limit);
172694
- const messages = yield* client.findAll(
172695
- chunter.class.ChatMessage,
172874
+ const messages = yield* target.client.findAll(
172875
+ activity.class.ActivityMessage,
172696
172876
  {
172697
- space: channel._id
172877
+ attachedTo: toRef(target.objectId),
172878
+ attachedToClass: toRef(target.objectClass)
172698
172879
  },
172699
172880
  {
172700
172881
  limit,
172701
172882
  sort: {
172702
- createdOn: import_core20.SortingOrder.Descending
172883
+ modifiedOn: import_core22.SortingOrder.Descending
172703
172884
  }
172704
172885
  }
172705
172886
  );
172706
- const total = messages.total;
172707
- const uniqueSocialIds = [
172708
- ...new Set(
172709
- messages.map((msg) => msg.modifiedBy)
172710
- )
172711
- ];
172712
- const socialIdToName = yield* buildSocialIdToPersonNameMap(client, uniqueSocialIds);
172713
- const summaries = messages.map((msg) => {
172714
- const senderName = socialIdToName.get(msg.modifiedBy);
172715
- return {
172716
- id: MessageId.make(msg._id),
172717
- body: markupToMarkdownString(msg.message, markupUrlConfig),
172718
- sender: senderName !== void 0 ? PersonName.make(senderName) : void 0,
172719
- senderId: msg.modifiedBy,
172720
- createdOn: msg.createdOn,
172721
- modifiedOn: msg.modifiedOn,
172722
- editedOn: msg.editedOn,
172723
- replies: msg.replies
172724
- };
172725
- });
172726
- return { messages: summaries, total };
172887
+ const result = messages.map((msg) => ({
172888
+ id: ActivityMessageId.make(msg._id),
172889
+ objectId: NonEmptyString2.make(msg.attachedTo),
172890
+ objectClass: ObjectClassName.make(msg.attachedToClass),
172891
+ modifiedBy: PersonId.make(msg.modifiedBy),
172892
+ modifiedOn: optionalTimestamp(msg.modifiedOn),
172893
+ isPinned: msg.isPinned,
172894
+ replies: optionalActivityCount(msg.replies),
172895
+ reactions: optionalActivityCount(msg.reactions),
172896
+ editedOn: optionalNullableTimestamp(msg.editedOn)
172897
+ }));
172898
+ return result;
172727
172899
  });
172728
- var sendChannelMessage = (params) => Effect_exports.gen(function* () {
172729
- const { channel, client } = yield* findChannel(params.channel);
172730
- const markupUrlConfig = client.markupUrlConfig;
172731
- const messageId = (0, import_core20.generateId)();
172732
- const markup = markdownToMarkupString(params.body, markupUrlConfig);
172733
- const messageData = {
172734
- message: markup,
172735
- attachments: 0
172900
+ var addReaction = (params) => Effect_exports.gen(function* () {
172901
+ const client = yield* HulyClient;
172902
+ const message = yield* findOneOrFail(
172903
+ client,
172904
+ activity.class.ActivityMessage,
172905
+ { _id: toRef(params.messageId) },
172906
+ () => new ActivityMessageNotFoundError({ messageId: params.messageId })
172907
+ );
172908
+ const reactionId = (0, import_core22.generateId)();
172909
+ const reactionData = {
172910
+ emoji: params.emoji,
172911
+ createBy: serverPopulatedCreateBy
172736
172912
  };
172737
172913
  yield* client.addCollection(
172738
- chunter.class.ChatMessage,
172739
- channel._id,
172740
- channel._id,
172741
- chunter.class.Channel,
172742
- "messages",
172743
- messageData,
172744
- messageId
172914
+ activity.class.Reaction,
172915
+ message.space,
172916
+ message._id,
172917
+ activity.class.ActivityMessage,
172918
+ "reactions",
172919
+ reactionData,
172920
+ reactionId
172745
172921
  );
172746
- return { id: MessageId.make(messageId), channelId: ChannelId.make(channel._id) };
172922
+ return {
172923
+ reactionId: ReactionId.make(reactionId),
172924
+ messageId: ActivityMessageId.make(params.messageId)
172925
+ };
172747
172926
  });
172748
- var listDirectMessages = (params) => Effect_exports.gen(function* () {
172927
+ var removeReaction = (params) => Effect_exports.gen(function* () {
172749
172928
  const client = yield* HulyClient;
172750
- const limit = clampLimit(params.limit);
172751
- const dms = yield* client.findAll(
172752
- chunter.class.DirectMessage,
172753
- { members: client.getAccountUuid() },
172929
+ const reaction = yield* findOneOrFail(
172930
+ client,
172931
+ activity.class.Reaction,
172754
172932
  {
172755
- limit,
172756
- sort: {
172757
- modifiedOn: import_core20.SortingOrder.Descending
172758
- }
172759
- }
172933
+ attachedTo: toRef(params.messageId),
172934
+ emoji: params.emoji
172935
+ },
172936
+ () => new ReactionNotFoundError({
172937
+ messageId: params.messageId,
172938
+ emoji: params.emoji
172939
+ })
172760
172940
  );
172761
- const total = dms.total;
172762
- const uniqueAccountUuids = [
172763
- ...new Set(
172764
- dms.flatMap((dm) => dm.members)
172765
- )
172766
- ];
172767
- const accountUuidToName = yield* buildAccountUuidToNameMap(client, uniqueAccountUuids);
172768
- const summaries = dms.map((dm) => {
172769
- const participants = dm.members.map((m) => accountUuidToName.get(m)).filter((n) => n !== void 0).map((n) => PersonName.make(n));
172770
- const participantIds = dm.members.map((m) => AccountUuid.make(m));
172771
- return {
172772
- id: ChannelId.make(dm._id),
172773
- participants,
172774
- participantIds,
172775
- messages: dm.messages,
172776
- modifiedOn: dm.modifiedOn
172777
- };
172778
- });
172779
- return { conversations: summaries, total };
172941
+ yield* client.removeDoc(
172942
+ activity.class.Reaction,
172943
+ reaction.space,
172944
+ reaction._id
172945
+ );
172946
+ return {
172947
+ messageId: ActivityMessageId.make(params.messageId),
172948
+ removed: true
172949
+ };
172780
172950
  });
172781
-
172782
- // src/huly/operations/documents-inline-comments.ts
172783
- var INLINE_COMMENT_MARK_TYPE = "inline-comment";
172784
- var extractInlineComments = (root) => {
172785
- const threadMap = /* @__PURE__ */ new Map();
172786
- (0, import_text3.traverseAllMarks)(root, (textNode, mark) => {
172787
- if (String(mark.type) !== INLINE_COMMENT_MARK_TYPE) return;
172788
- const threadId = mark.attrs?.thread;
172789
- if (typeof threadId !== "string" || threadId === "") return;
172790
- const text = textNode.text ?? "";
172791
- if (!threadMap.has(threadId)) {
172792
- threadMap.set(threadId, []);
172793
- }
172794
- threadMap.get(threadId)?.push(text);
172795
- });
172796
- return [...threadMap.entries()].map(([threadId, textFragments]) => ({
172797
- threadId,
172798
- textFragments
172951
+ var listReactions = (params) => Effect_exports.gen(function* () {
172952
+ const client = yield* HulyClient;
172953
+ const limit = clampLimit(params.limit);
172954
+ const reactions = yield* client.findAll(
172955
+ activity.class.Reaction,
172956
+ {
172957
+ attachedTo: toRef(params.messageId)
172958
+ },
172959
+ { limit }
172960
+ );
172961
+ const result = reactions.map((r) => ({
172962
+ id: ReactionId.make(r._id),
172963
+ messageId: ActivityMessageId.make(r.attachedTo),
172964
+ emoji: EmojiCode.make(r.emoji),
172965
+ createdBy: optionalPersonId(r.createBy)
172799
172966
  }));
172800
- };
172801
- var listInlineComments = (params) => Effect_exports.gen(function* () {
172802
- const { client, doc } = yield* findTeamspaceAndDocument({
172803
- teamspace: params.teamspace,
172804
- document: params.document
172805
- });
172806
- const markupUrlConfig = client.markupUrlConfig;
172807
- if (!doc.content) {
172808
- return { comments: [], total: 0 };
172809
- }
172810
- const rawMarkup = yield* client.fetchMarkup(
172811
- doc._class,
172812
- doc._id,
172813
- "content",
172814
- doc.content,
172815
- "markup"
172967
+ return result;
172968
+ });
172969
+ var saveMessage = (params) => Effect_exports.gen(function* () {
172970
+ const client = yield* HulyClient;
172971
+ const message = yield* findOneOrFail(
172972
+ client,
172973
+ activity.class.ActivityMessage,
172974
+ { _id: toRef(params.messageId) },
172975
+ () => new ActivityMessageNotFoundError({ messageId: params.messageId })
172816
172976
  );
172817
- const root = (0, import_text3.markupToJSON)(rawMarkup);
172818
- const extracted = extractInlineComments(root);
172819
- if (extracted.length === 0) {
172820
- return { comments: [], total: 0 };
172821
- }
172822
- let nameMap = /* @__PURE__ */ new Map();
172823
- const threadRepliesMap = /* @__PURE__ */ new Map();
172824
- if (params.includeReplies) {
172825
- const threadIds = extracted.map((c) => toRef(c.threadId));
172826
- const allReplies = yield* client.findAll(
172827
- chunter.class.ThreadMessage,
172828
- { attachedTo: { $in: threadIds } },
172829
- { sort: { createdOn: import_core21.SortingOrder.Ascending } }
172830
- );
172831
- for (const r of allReplies) {
172832
- const key = r.attachedTo;
172833
- if (!threadRepliesMap.has(key)) {
172834
- threadRepliesMap.set(key, []);
172835
- }
172836
- threadRepliesMap.get(key)?.push(r);
172837
- }
172838
- const senderIds = [
172839
- ...new Set(
172840
- allReplies.map((r) => r.createdBy).filter((id) => id !== void 0)
172841
- )
172842
- ];
172843
- nameMap = yield* buildSocialIdToPersonNameMap(client, senderIds);
172844
- }
172845
- const comments = extracted.map((comment) => {
172846
- const thread = {
172847
- threadId: comment.threadId,
172848
- text: comment.textFragments.join("")
172849
- };
172850
- if (params.includeReplies) {
172851
- const threadReplies = threadRepliesMap.get(comment.threadId) ?? [];
172852
- const replies = threadReplies.map((r) => ({
172853
- id: r._id,
172854
- body: optionalMarkupToMarkdown(r.message, markupUrlConfig, ""),
172855
- sender: r.createdBy !== void 0 ? nameMap.get(r.createdBy) : void 0,
172856
- createdOn: r.createdOn
172857
- }));
172858
- return { ...thread, replies };
172859
- }
172860
- return thread;
172861
- });
172862
- return { comments, total: comments.length };
172977
+ const savedId = (0, import_core22.generateId)();
172978
+ yield* client.createDoc(
172979
+ activity.class.SavedMessage,
172980
+ core.space.Workspace,
172981
+ {
172982
+ attachedTo: message._id
172983
+ },
172984
+ savedId
172985
+ );
172986
+ return {
172987
+ savedId: SavedMessageId.make(savedId),
172988
+ messageId: ActivityMessageId.make(params.messageId)
172989
+ };
172863
172990
  });
172864
-
172865
- // src/huly/operations/documents.ts
172866
- var findTeamspace = (identifier2, opts) => Effect_exports.gen(function* () {
172991
+ var unsaveMessage = (params) => Effect_exports.gen(function* () {
172867
172992
  const client = yield* HulyClient;
172868
- const nameQuery = { name: identifier2 };
172869
- const idQuery = { _id: toRef(identifier2) };
172870
- if (!opts?.includeArchived) {
172871
- nameQuery.archived = false;
172872
- idQuery.archived = false;
172873
- }
172874
- const teamspace = yield* findByNameOrId(
172993
+ const saved = yield* findOneOrFail(
172875
172994
  client,
172876
- documentPlugin.class.Teamspace,
172877
- nameQuery,
172878
- idQuery
172995
+ activity.class.SavedMessage,
172996
+ {
172997
+ attachedTo: toRef(params.messageId)
172998
+ },
172999
+ () => new SavedMessageNotFoundError({ messageId: params.messageId })
172879
173000
  );
172880
- if (teamspace === void 0) {
172881
- return yield* new TeamspaceNotFoundError({ identifier: identifier2 });
172882
- }
172883
- return { client, teamspace };
173001
+ yield* client.removeDoc(
173002
+ activity.class.SavedMessage,
173003
+ saved.space,
173004
+ saved._id
173005
+ );
173006
+ return {
173007
+ messageId: ActivityMessageId.make(params.messageId),
173008
+ removed: true
173009
+ };
172884
173010
  });
172885
- var findTeamspaceAndDocument = (params) => Effect_exports.gen(function* () {
172886
- const { client, teamspace } = yield* findTeamspace(params.teamspace);
172887
- const doc = yield* findByNameOrId(
172888
- client,
172889
- documentPlugin.class.Document,
172890
- { space: teamspace._id, title: params.document },
172891
- { space: teamspace._id, _id: toRef(params.document) }
173011
+ var listSavedMessages = (params) => Effect_exports.gen(function* () {
173012
+ const client = yield* HulyClient;
173013
+ const limit = clampLimit(params.limit);
173014
+ const saved = yield* client.findAll(
173015
+ activity.class.SavedMessage,
173016
+ {},
173017
+ { limit }
172892
173018
  );
172893
- if (doc === void 0) {
172894
- return yield* new DocumentNotFoundError({
172895
- identifier: params.document,
172896
- teamspace: params.teamspace
172897
- });
172898
- }
172899
- return { client, teamspace, doc };
173019
+ const result = saved.map((s) => ({
173020
+ id: SavedMessageId.make(s._id),
173021
+ messageId: ActivityMessageId.make(s.attachedTo)
173022
+ }));
173023
+ return result;
172900
173024
  });
172901
- var listTeamspaces = (params) => Effect_exports.gen(function* () {
173025
+ var listMentions = (params) => Effect_exports.gen(function* () {
172902
173026
  const client = yield* HulyClient;
172903
- const query = {};
172904
- if (!params.includeArchived) {
172905
- query.archived = false;
172906
- }
172907
173027
  const limit = clampLimit(params.limit);
172908
- const teamspaces = yield* client.findAll(
172909
- documentPlugin.class.Teamspace,
172910
- query,
173028
+ const mentions = yield* client.findAll(
173029
+ activity.class.UserMentionInfo,
173030
+ {},
172911
173031
  {
172912
173032
  limit,
172913
173033
  sort: {
172914
- name: import_core22.SortingOrder.Ascending
173034
+ modifiedOn: import_core22.SortingOrder.Descending
172915
173035
  }
172916
173036
  }
172917
173037
  );
172918
- const total = teamspaces.total;
172919
- const summaries = teamspaces.map((ts) => ({
172920
- id: TeamspaceId.make(ts._id),
172921
- name: ts.name,
172922
- description: ts.description || void 0,
172923
- archived: ts.archived,
172924
- private: ts.private
173038
+ const result = mentions.map((m) => ({
173039
+ id: MentionId.make(m._id),
173040
+ messageId: ActivityMessageId.make(m.attachedTo),
173041
+ userId: PersonId.make(m.user),
173042
+ content: m.content
172925
173043
  }));
172926
- return {
172927
- teamspaces: summaries,
172928
- total
172929
- };
172930
- });
172931
- var getTeamspace = (params) => Effect_exports.gen(function* () {
172932
- const { client, teamspace } = yield* findTeamspace(params.teamspace, { includeArchived: true });
172933
- const docs = yield* client.findAll(
172934
- documentPlugin.class.Document,
172935
- { space: teamspace._id },
172936
- { limit: 1, total: true }
172937
- );
172938
- return {
172939
- id: TeamspaceId.make(teamspace._id),
172940
- name: teamspace.name,
172941
- description: teamspace.description || void 0,
172942
- archived: teamspace.archived,
172943
- private: teamspace.private,
172944
- documents: docs.total
172945
- };
172946
- });
172947
- var createTeamspace = (params) => Effect_exports.gen(function* () {
172948
- const client = yield* HulyClient;
172949
- const existing = yield* client.findOne(
172950
- documentPlugin.class.Teamspace,
172951
- { name: params.name, archived: false }
172952
- );
172953
- if (existing !== void 0) {
172954
- return {
172955
- id: TeamspaceId.make(existing._id),
172956
- name: existing.name,
172957
- created: false
172958
- };
172959
- }
172960
- const teamspaceId = (0, import_core22.generateId)();
172961
- const teamspaceData = {
172962
- name: params.name,
172963
- description: params.description ?? "",
172964
- private: params.private ?? false,
172965
- archived: false,
172966
- members: [client.getAccountUuid()],
172967
- owners: [client.getAccountUuid()],
172968
- icon: documentPlugin.icon.Teamspace,
172969
- type: documentPlugin.spaceType.DefaultTeamspaceType
172970
- };
172971
- yield* client.createDoc(
172972
- documentPlugin.class.Teamspace,
172973
- core.space.Space,
172974
- teamspaceData,
172975
- teamspaceId
172976
- );
172977
- return {
172978
- id: TeamspaceId.make(teamspaceId),
172979
- name: params.name,
172980
- created: true
172981
- };
173044
+ return result;
172982
173045
  });
172983
- var updateTeamspace = (params) => Effect_exports.gen(function* () {
172984
- const { client, teamspace } = yield* findTeamspace(params.teamspace, { includeArchived: true });
172985
- const updateOps = {};
172986
- if (params.name !== void 0) {
172987
- updateOps.name = params.name;
173046
+
173047
+ // src/mcp/tools/registry.ts
173048
+ var deriveTitle = (name) => name.split("_").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
173049
+ var READ_PREFIXES = ["list_", "get_", "search_", "fulltext_", "download_", "preview_"];
173050
+ var CREATE_PREFIXES = ["create_", "add_", "upload_", "send_", "log_"];
173051
+ var UPDATE_PREFIXES = [
173052
+ "update_",
173053
+ "edit_",
173054
+ "set_",
173055
+ "pin_",
173056
+ "unpin_",
173057
+ "mark_",
173058
+ "archive_",
173059
+ "start_",
173060
+ "stop_",
173061
+ "save_",
173062
+ "unsave_",
173063
+ "remove_",
173064
+ "move_"
173065
+ ];
173066
+ var DELETE_PREFIXES = ["delete_"];
173067
+ var matchesPrefix = (name, prefixes) => prefixes.some((p) => name.startsWith(p));
173068
+ var deriveAnnotations = (name) => {
173069
+ const title = deriveTitle(name);
173070
+ if (matchesPrefix(name, READ_PREFIXES)) {
173071
+ return { title, readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
172988
173072
  }
172989
- if (params.description !== void 0) {
172990
- updateOps.description = params.description === null ? "" : params.description;
173073
+ if (matchesPrefix(name, CREATE_PREFIXES)) {
173074
+ return { title, readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false };
172991
173075
  }
172992
- if (params.archived !== void 0) {
172993
- updateOps.archived = params.archived;
173076
+ if (matchesPrefix(name, UPDATE_PREFIXES)) {
173077
+ return { title, readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false };
172994
173078
  }
172995
- if (Object.keys(updateOps).length === 0) {
172996
- return { id: TeamspaceId.make(teamspace._id), updated: false };
173079
+ if (matchesPrefix(name, DELETE_PREFIXES)) {
173080
+ return { title, readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false };
172997
173081
  }
172998
- yield* client.updateDoc(
172999
- documentPlugin.class.Teamspace,
173000
- core.space.Space,
173001
- teamspace._id,
173002
- updateOps
173003
- );
173004
- return { id: TeamspaceId.make(teamspace._id), updated: true };
173005
- });
173006
- var deleteTeamspace = (params) => Effect_exports.gen(function* () {
173007
- const { client, teamspace } = yield* findTeamspace(params.teamspace, { includeArchived: true });
173008
- yield* client.removeDoc(
173009
- documentPlugin.class.Teamspace,
173010
- core.space.Space,
173011
- teamspace._id
173012
- );
173013
- return { id: TeamspaceId.make(teamspace._id), deleted: true };
173082
+ return { title, readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false };
173083
+ };
173084
+ var resolveAnnotations = (tool) => ({
173085
+ ...deriveAnnotations(tool.name),
173086
+ ...tool.annotations
173014
173087
  });
173015
- var listDocuments = (params) => Effect_exports.gen(function* () {
173016
- const { client, teamspace } = yield* findTeamspace(params.teamspace);
173017
- const limit = clampLimit(params.limit);
173018
- const query = {
173019
- space: teamspace._id
173020
- };
173021
- if (params.titleSearch !== void 0 && params.titleSearch.trim() !== "") {
173022
- query.title = { $like: `%${escapeLikeWildcards(params.titleSearch)}%` };
173088
+ var encodeOutput = (schema, result) => Schema_exports.encodeUnknownSync(schema)(result);
173089
+ var provideHulyClient = (args2) => (effect2) => Either_exports.right(effect2.pipe(Effect_exports.provideService(HulyClient, args2.hulyClient)));
173090
+ var provideStorageClient = (args2) => (effect2) => Either_exports.right(effect2.pipe(Effect_exports.provideService(HulyStorageClient, args2.storageClient)));
173091
+ var provideCombinedClient = (args2) => (effect2) => Either_exports.right(
173092
+ effect2.pipe(
173093
+ Effect_exports.provideService(HulyClient, args2.hulyClient),
173094
+ Effect_exports.provideService(HulyStorageClient, args2.storageClient)
173095
+ )
173096
+ );
173097
+ var provideWorkspaceClient = (args2) => (effect2) => args2.workspaceClient !== void 0 ? Either_exports.right(effect2.pipe(Effect_exports.provideService(WorkspaceClient, args2.workspaceClient))) : Either_exports.left(mapDomainErrorToMcp(new HulyError({ message: "WorkspaceClient not available" })));
173098
+ var createHandler = (toolName, provide4, parse5, operation, encode8) => async (args2, hulyClient, storageClient, workspaceClient) => {
173099
+ const parseResult = await Effect_exports.runPromiseExit(parse5(args2));
173100
+ if (Exit_exports.isFailure(parseResult)) {
173101
+ return mapParseCauseToMcp(parseResult.cause, toolName);
173023
173102
  }
173024
- if (params.titleRegex !== void 0 && params.titleRegex.trim() !== "") {
173025
- query.title = { $regex: params.titleRegex };
173103
+ const provided = provide4({ hulyClient, storageClient, workspaceClient })(operation(parseResult.value));
173104
+ if (Either_exports.isLeft(provided)) {
173105
+ return provided.left;
173026
173106
  }
173027
- if (params.contentSearch !== void 0 && params.contentSearch.trim() !== "") {
173028
- query.$search = params.contentSearch;
173107
+ const operationResult = await Effect_exports.runPromiseExit(provided.right);
173108
+ if (Exit_exports.isFailure(operationResult)) {
173109
+ return mapDomainCauseToMcp(operationResult.cause);
173110
+ }
173111
+ try {
173112
+ const output = encode8 !== void 0 ? encode8(operationResult.value) : operationResult.value;
173113
+ return createSuccessResponse(output);
173114
+ } catch {
173115
+ return mapDomainErrorToMcp(new HulyError({ message: `Tool ${toolName} produced invalid output` }));
173116
+ }
173117
+ };
173118
+ var createToolHandler = (toolName, parse5, operation) => createHandler(toolName, provideHulyClient, parse5, operation);
173119
+ var createEncodedToolHandler = (toolName, parse5, operation, outputSchema) => createHandler(
173120
+ toolName,
173121
+ provideHulyClient,
173122
+ parse5,
173123
+ operation,
173124
+ (result) => encodeOutput(outputSchema, result)
173125
+ );
173126
+ var createStorageToolHandler = (toolName, parse5, operation) => createHandler(toolName, provideStorageClient, parse5, operation);
173127
+ var createCombinedToolHandler = (toolName, parse5, operation) => createHandler(toolName, provideCombinedClient, parse5, operation);
173128
+ var createEncodedWorkspaceToolHandler = (toolName, parse5, operation, outputSchema) => createHandler(
173129
+ toolName,
173130
+ provideWorkspaceClient,
173131
+ parse5,
173132
+ operation,
173133
+ (result) => encodeOutput(outputSchema, result)
173134
+ );
173135
+ var createEncodedNoParamsWorkspaceToolHandler = (toolName, operation, outputSchema) => createHandler(
173136
+ toolName,
173137
+ provideWorkspaceClient,
173138
+ () => Effect_exports.succeed(void 0),
173139
+ operation,
173140
+ (result) => encodeOutput(outputSchema, result)
173141
+ );
173142
+
173143
+ // src/mcp/tools/activity.ts
173144
+ var CATEGORY = "activity";
173145
+ var activityTools = [
173146
+ {
173147
+ name: "list_activity",
173148
+ description: "List activity messages for a Huly issue, document, channel, or raw Huly object. Prefer friendly targets: project+issueIdentifier for issues, teamspace+document for documents, or channel for channels. Advanced callers may pass objectId+objectClass directly. Returns activity sorted by date (newest first).",
173149
+ category: CATEGORY,
173150
+ inputSchema: listActivityParamsJsonSchema,
173151
+ handler: createEncodedToolHandler(
173152
+ "list_activity",
173153
+ parseListActivityParams,
173154
+ listActivity,
173155
+ ListActivityResultSchema
173156
+ )
173157
+ },
173158
+ {
173159
+ name: "add_reaction",
173160
+ description: "Add an emoji reaction to an activity message.",
173161
+ category: CATEGORY,
173162
+ inputSchema: addReactionParamsJsonSchema,
173163
+ handler: createEncodedToolHandler(
173164
+ "add_reaction",
173165
+ parseAddReactionParams,
173166
+ addReaction,
173167
+ AddReactionResultSchema
173168
+ )
173169
+ },
173170
+ {
173171
+ name: "remove_reaction",
173172
+ description: "Remove an emoji reaction from an activity message.",
173173
+ category: CATEGORY,
173174
+ inputSchema: removeReactionParamsJsonSchema,
173175
+ handler: createEncodedToolHandler(
173176
+ "remove_reaction",
173177
+ parseRemoveReactionParams,
173178
+ removeReaction,
173179
+ RemoveReactionResultSchema
173180
+ )
173181
+ },
173182
+ {
173183
+ name: "list_reactions",
173184
+ description: "List reactions on an activity message.",
173185
+ category: CATEGORY,
173186
+ inputSchema: listReactionsParamsJsonSchema,
173187
+ handler: createEncodedToolHandler(
173188
+ "list_reactions",
173189
+ parseListReactionsParams,
173190
+ listReactions,
173191
+ ListReactionsResultSchema
173192
+ )
173193
+ },
173194
+ {
173195
+ name: "save_message",
173196
+ description: "Save/bookmark an activity message for later reference.",
173197
+ category: CATEGORY,
173198
+ inputSchema: saveMessageParamsJsonSchema,
173199
+ handler: createEncodedToolHandler(
173200
+ "save_message",
173201
+ parseSaveMessageParams,
173202
+ saveMessage,
173203
+ SaveMessageResultSchema
173204
+ )
173205
+ },
173206
+ {
173207
+ name: "unsave_message",
173208
+ description: "Remove an activity message from saved/bookmarks.",
173209
+ category: CATEGORY,
173210
+ inputSchema: unsaveMessageParamsJsonSchema,
173211
+ handler: createEncodedToolHandler(
173212
+ "unsave_message",
173213
+ parseUnsaveMessageParams,
173214
+ unsaveMessage,
173215
+ UnsaveMessageResultSchema
173216
+ )
173217
+ },
173218
+ {
173219
+ name: "list_saved_messages",
173220
+ description: "List saved/bookmarked activity messages.",
173221
+ category: CATEGORY,
173222
+ inputSchema: listSavedMessagesParamsJsonSchema,
173223
+ handler: createEncodedToolHandler(
173224
+ "list_saved_messages",
173225
+ parseListSavedMessagesParams,
173226
+ listSavedMessages,
173227
+ ListSavedMessagesResultSchema
173228
+ )
173229
+ },
173230
+ {
173231
+ name: "list_mentions",
173232
+ description: "List @mentions of the current user in activity messages.",
173233
+ category: CATEGORY,
173234
+ inputSchema: listMentionsParamsJsonSchema,
173235
+ handler: createEncodedToolHandler(
173236
+ "list_mentions",
173237
+ parseListMentionsParams,
173238
+ listMentions,
173239
+ ListMentionsResultSchema
173240
+ )
173029
173241
  }
173030
- const documents = yield* client.findAll(
173031
- documentPlugin.class.Document,
173032
- query,
173033
- {
173034
- limit,
173035
- sort: {
173036
- modifiedOn: import_core22.SortingOrder.Descending
173037
- }
173038
- }
173039
- );
173040
- const total = documents.total;
173041
- const summaries = documents.map((doc) => ({
173042
- id: DocumentId.make(doc._id),
173043
- title: doc.title,
173044
- teamspace: teamspace.name,
173045
- url: buildDocumentUrlFromConfig(client.workbenchUrlConfig, doc.title, DocumentId.make(doc._id)),
173046
- modifiedOn: doc.modifiedOn
173047
- }));
173048
- return {
173049
- documents: summaries,
173050
- total
173051
- };
173242
+ ];
173243
+
173244
+ // src/domain/schemas/attachments.ts
173245
+ var ListAttachmentsParamsSchema = Schema_exports.Struct({
173246
+ objectId: NonEmptyString2.annotations({
173247
+ description: "ID of the parent object (issue, document, etc.)"
173248
+ }),
173249
+ objectClass: ObjectClassName.annotations({
173250
+ description: "Class of the parent object (e.g., 'tracker:class:Issue', 'document:class:Document')"
173251
+ }),
173252
+ limit: Schema_exports.optional(
173253
+ LimitParam.annotations({
173254
+ description: "Maximum number of attachments to return (default: 50)"
173255
+ })
173256
+ )
173257
+ }).annotations({
173258
+ title: "ListAttachmentsParams",
173259
+ description: "Parameters for listing attachments on an object"
173052
173260
  });
173053
- var getDocument = (params) => Effect_exports.gen(function* () {
173054
- const { client, doc, teamspace } = yield* findTeamspaceAndDocument({
173055
- teamspace: params.teamspace,
173056
- document: params.document
173057
- });
173058
- const content = doc.content ? yield* client.fetchMarkup(
173059
- doc._class,
173060
- doc._id,
173061
- "content",
173062
- doc.content,
173063
- "markdown"
173064
- ) : void 0;
173065
- const result = {
173066
- id: DocumentId.make(doc._id),
173067
- title: doc.title,
173068
- content,
173069
- teamspace: teamspace.name,
173070
- url: buildDocumentUrlFromConfig(client.workbenchUrlConfig, doc.title, DocumentId.make(doc._id)),
173071
- modifiedOn: doc.modifiedOn,
173072
- createdOn: doc.createdOn
173073
- };
173074
- return result;
173261
+ var GetAttachmentParamsSchema = Schema_exports.Struct({
173262
+ attachmentId: AttachmentId.annotations({
173263
+ description: "Attachment ID"
173264
+ })
173265
+ }).annotations({
173266
+ title: "GetAttachmentParams",
173267
+ description: "Parameters for getting a single attachment"
173075
173268
  });
173076
- var createDocument = (params) => Effect_exports.gen(function* () {
173077
- const { client, teamspace } = yield* findTeamspace(params.teamspace);
173078
- const documentId = (0, import_core22.generateId)();
173079
- const parent = params.parent;
173080
- const parentRef = parent === void 0 ? documentPlugin.ids.NoParent : yield* Effect_exports.gen(function* () {
173081
- const parentDoc = yield* findByNameOrId(
173082
- client,
173083
- documentPlugin.class.Document,
173084
- { space: teamspace._id, title: parent },
173085
- { space: teamspace._id, _id: toRef(parent) }
173086
- );
173087
- if (parentDoc === void 0) {
173088
- return yield* new DocumentNotFoundError({
173089
- identifier: parent,
173090
- teamspace: params.teamspace
173091
- });
173092
- }
173093
- return parentDoc._id;
173094
- });
173095
- const lastDoc = yield* client.findOne(
173096
- documentPlugin.class.Document,
173097
- { space: teamspace._id },
173098
- { sort: { rank: import_core22.SortingOrder.Descending } }
173099
- );
173100
- const rank = (0, import_rank.makeRank)(lastDoc?.rank, void 0);
173101
- const contentMarkupRef = params.content !== void 0 && params.content.trim() !== "" ? yield* client.uploadMarkup(
173102
- documentPlugin.class.Document,
173103
- documentId,
173104
- "content",
173105
- params.content,
173106
- "markdown"
173107
- ) : null;
173108
- const documentData = {
173109
- title: params.title,
173110
- content: contentMarkupRef,
173111
- parent: parentRef,
173112
- rank
173113
- };
173114
- yield* client.createDoc(
173115
- documentPlugin.class.Document,
173116
- teamspace._id,
173117
- documentData,
173118
- documentId
173119
- );
173120
- return {
173121
- id: DocumentId.make(documentId),
173122
- title: params.title,
173123
- url: buildDocumentUrlFromConfig(client.workbenchUrlConfig, params.title, DocumentId.make(documentId))
173124
- };
173269
+ var FileSourceFields = {
173270
+ filename: NonEmptyString2.annotations({
173271
+ description: "Name of the file"
173272
+ }),
173273
+ contentType: MimeType.annotations({
173274
+ description: "MIME type of the file (e.g., 'image/png', 'application/pdf')"
173275
+ }),
173276
+ filePath: Schema_exports.optional(Schema_exports.String.annotations({
173277
+ description: "Local file path to upload (preferred - avoids context flooding)"
173278
+ })),
173279
+ fileUrl: Schema_exports.optional(Schema_exports.String.annotations({
173280
+ description: "URL to fetch file from (for remote files)"
173281
+ })),
173282
+ data: Schema_exports.optional(Schema_exports.String.annotations({
173283
+ description: "Base64-encoded file data (fallback for small files <10KB)"
173284
+ })),
173285
+ description: Schema_exports.optional(Schema_exports.String.annotations({
173286
+ description: "Attachment description"
173287
+ })),
173288
+ pinned: Schema_exports.optional(Schema_exports.Boolean.annotations({
173289
+ description: "Whether to pin the attachment (default: false)"
173290
+ }))
173291
+ };
173292
+ var hasFileSource = (params) => {
173293
+ const hasSource = params.filePath || params.fileUrl || params.data;
173294
+ return hasSource ? true : "Must provide filePath, fileUrl, or data";
173295
+ };
173296
+ var AddAttachmentParamsBase = Schema_exports.Struct({
173297
+ objectId: NonEmptyString2.annotations({
173298
+ description: "ID of the parent object (issue, document, etc.)"
173299
+ }),
173300
+ objectClass: ObjectClassName.annotations({
173301
+ description: "Class of the parent object (e.g., 'tracker:class:Issue', 'document:class:Document')"
173302
+ }),
173303
+ space: SpaceId.annotations({
173304
+ description: "Space ID where the parent object resides"
173305
+ }),
173306
+ ...FileSourceFields
173125
173307
  });
173126
- var deleteDocument = (params) => Effect_exports.gen(function* () {
173127
- const { client, doc, teamspace } = yield* findTeamspaceAndDocument(params);
173128
- yield* client.removeDoc(
173129
- documentPlugin.class.Document,
173130
- teamspace._id,
173131
- doc._id
173132
- );
173133
- return { id: DocumentId.make(doc._id), deleted: true };
173308
+ var AddAttachmentParamsSchema = AddAttachmentParamsBase.pipe(
173309
+ Schema_exports.filter(hasFileSource)
173310
+ ).annotations({
173311
+ title: "AddAttachmentParams",
173312
+ description: "Parameters for adding an attachment. Provide ONE of: filePath, fileUrl, or data"
173134
173313
  });
173135
-
173136
- // src/huly/operations/issues-shared.ts
173137
- var import_tracker = __toESM(require_lib36(), 1);
173138
-
173139
- // src/utils/normalize.ts
173140
- var normalizeForComparison = (s) => s.replace(/[-_ ]/g, "").toLowerCase();
173141
-
173142
- // src/huly/operations/issues-shared.ts
173143
- var zeroAsUnset = (value3) => value3 > 0 ? PositiveNumber.make(value3) : void 0;
173144
- var findProject = (projectIdentifier) => Effect_exports.gen(function* () {
173145
- const client = yield* HulyClient;
173146
- const project3 = yield* findOneOrFail(
173147
- client,
173148
- tracker.class.Project,
173149
- { identifier: projectIdentifier },
173150
- () => new ProjectNotFoundError({ identifier: projectIdentifier })
173151
- );
173152
- return { client, project: project3 };
173314
+ var UpdateAttachmentParamsSchema = Schema_exports.Struct({
173315
+ attachmentId: AttachmentId.annotations({
173316
+ description: "Attachment ID"
173317
+ }),
173318
+ description: Schema_exports.optional(
173319
+ Schema_exports.NullOr(Schema_exports.String).annotations({
173320
+ description: "New description (null to clear)"
173321
+ })
173322
+ ),
173323
+ pinned: Schema_exports.optional(Schema_exports.Boolean.annotations({
173324
+ description: "Pin or unpin the attachment"
173325
+ }))
173326
+ }).annotations({
173327
+ title: "UpdateAttachmentParams",
173328
+ description: "Parameters for updating an attachment"
173153
173329
  });
173154
- var findProjectWithStatuses = (projectIdentifier) => Effect_exports.gen(function* () {
173155
- const client = yield* HulyClient;
173156
- const project3 = yield* findOneOrFail(
173157
- client,
173158
- tracker.class.Project,
173159
- { identifier: projectIdentifier },
173160
- () => new ProjectNotFoundError({ identifier: projectIdentifier }),
173161
- { lookup: { type: task.class.ProjectType } }
173162
- );
173163
- const projectType = project3.$lookup?.type;
173164
- const statuses = [];
173165
- if (projectType?.statuses) {
173166
- const statusRefs = projectType.statuses.map((s) => s._id);
173167
- if (statusRefs.length > 0) {
173168
- const statusDocsResult = yield* Effect_exports.either(
173169
- client.findAll(
173170
- core.class.Status,
173171
- { _id: { $in: statusRefs } }
173172
- )
173173
- );
173174
- if (statusDocsResult._tag === "Right") {
173175
- for (const doc of statusDocsResult.right) {
173176
- const categoryStr = doc.category ? doc.category : "";
173177
- statuses.push({
173178
- _id: doc._id,
173179
- name: doc.name,
173180
- isDone: categoryStr === task.statusCategory.Won,
173181
- isCanceled: categoryStr === task.statusCategory.Lost
173182
- });
173183
- }
173184
- } else {
173185
- yield* Effect_exports.logWarning(
173186
- `Status query failed for project ${projectIdentifier}, using fallback. Category-based filtering (open/done/canceled) will use name heuristics. Error: ${statusDocsResult.left.message}`
173187
- );
173188
- for (const ps of projectType.statuses) {
173189
- const name = ps._id.split(":").pop() ?? "Unknown";
173190
- const nameLower = name.toLowerCase();
173191
- const isDone5 = nameLower.includes("done") || nameLower.includes("complete") || nameLower.includes("finished") || nameLower.includes("resolved") || nameLower.includes("closed");
173192
- const isCanceled = nameLower.includes("cancel") || nameLower.includes("reject") || nameLower.includes("abort") || nameLower.includes("wontfix") || nameLower.includes("invalid");
173193
- statuses.push({
173194
- _id: ps._id,
173195
- name,
173196
- isDone: isDone5,
173197
- isCanceled
173198
- });
173199
- }
173200
- }
173201
- }
173202
- }
173203
- const defaultStatusId = project3.defaultIssueStatus || statuses[0]?._id;
173204
- return { client, project: project3, statuses, defaultStatusId };
173330
+ var DeleteAttachmentParamsSchema = Schema_exports.Struct({
173331
+ attachmentId: AttachmentId.annotations({
173332
+ description: "Attachment ID to delete"
173333
+ })
173334
+ }).annotations({
173335
+ title: "DeleteAttachmentParams",
173336
+ description: "Parameters for deleting an attachment"
173205
173337
  });
173206
- var parseIssueIdentifier = (identifier2, projectIdentifier) => {
173207
- const idStr = String(identifier2).trim();
173208
- const match16 = idStr.match(/^([A-Z]+)-(\d+)$/i);
173209
- if (match16) {
173210
- return {
173211
- fullIdentifier: `${match16[1].toUpperCase()}-${match16[2]}`,
173212
- number: parseInt(match16[2], 10)
173213
- };
173214
- }
173215
- const numMatch = idStr.match(/^\d+$/);
173216
- if (numMatch) {
173217
- const num = parseInt(idStr, 10);
173218
- return {
173219
- fullIdentifier: `${projectIdentifier.toUpperCase()}-${num}`,
173220
- number: num
173221
- };
173222
- }
173223
- return { fullIdentifier: idStr, number: null };
173224
- };
173225
- var findIssueInProject = (client, project3, identifierStr) => Effect_exports.gen(function* () {
173226
- const { fullIdentifier, number: number8 } = parseIssueIdentifier(
173227
- identifierStr,
173228
- project3.identifier
173229
- );
173230
- const issue2 = (yield* client.findOne(
173231
- tracker.class.Issue,
173232
- {
173233
- space: project3._id,
173234
- identifier: fullIdentifier
173235
- }
173236
- )) ?? (number8 !== null ? yield* client.findOne(
173237
- tracker.class.Issue,
173238
- {
173239
- space: project3._id,
173240
- number: number8
173241
- }
173242
- ) : void 0);
173243
- if (issue2 === void 0) {
173244
- return yield* new IssueNotFoundError({
173245
- identifier: identifierStr,
173246
- project: project3.identifier
173247
- });
173248
- }
173249
- return issue2;
173338
+ var PinAttachmentParamsSchema = Schema_exports.Struct({
173339
+ attachmentId: AttachmentId.annotations({
173340
+ description: "Attachment ID"
173341
+ }),
173342
+ pinned: Schema_exports.Boolean.annotations({
173343
+ description: "Whether to pin (true) or unpin (false)"
173344
+ })
173345
+ }).annotations({
173346
+ title: "PinAttachmentParams",
173347
+ description: "Parameters for pinning/unpinning an attachment"
173250
173348
  });
173251
- var findProjectAndIssue = (params) => Effect_exports.gen(function* () {
173252
- const { client, project: project3 } = yield* findProject(params.project);
173253
- const issue2 = yield* findIssueInProject(client, project3, params.identifier);
173254
- return { client, project: project3, issue: issue2 };
173349
+ var DownloadAttachmentParamsSchema = Schema_exports.Struct({
173350
+ attachmentId: AttachmentId.annotations({
173351
+ description: "Attachment ID"
173352
+ })
173353
+ }).annotations({
173354
+ title: "DownloadAttachmentParams",
173355
+ description: "Parameters for getting attachment download URL"
173255
173356
  });
173256
- var priorityToStringMap = {
173257
- [import_tracker.IssuePriority.Urgent]: "urgent",
173258
- [import_tracker.IssuePriority.High]: "high",
173259
- [import_tracker.IssuePriority.Medium]: "medium",
173260
- [import_tracker.IssuePriority.Low]: "low",
173261
- [import_tracker.IssuePriority.NoPriority]: "no-priority"
173262
- };
173263
- var priorityToString = (priority) => priorityToStringMap[priority];
173264
- var stringToPriorityMap = {
173265
- "urgent": import_tracker.IssuePriority.Urgent,
173266
- "high": import_tracker.IssuePriority.High,
173267
- "medium": import_tracker.IssuePriority.Medium,
173268
- "low": import_tracker.IssuePriority.Low,
173269
- "no-priority": import_tracker.IssuePriority.NoPriority
173270
- };
173271
- var stringToPriority = (priority) => stringToPriorityMap[priority];
173272
- var resolveStatusByName = (statuses, statusName, project3) => {
173273
- const normalizedInput = normalizeForComparison(statusName);
173274
- const matchingStatus = statuses.find(
173275
- (s) => normalizeForComparison(s.name) === normalizedInput
173276
- );
173277
- if (matchingStatus === void 0) {
173278
- return Effect_exports.fail(new InvalidStatusError({ status: statusName, project: project3 }));
173279
- }
173280
- return Effect_exports.succeed(matchingStatus._id);
173281
- };
173357
+ var AddIssueAttachmentParamsBase = Schema_exports.Struct({
173358
+ project: ProjectIdentifier.annotations({
173359
+ description: "Project identifier (e.g., 'HULY')"
173360
+ }),
173361
+ identifier: IssueIdentifier.annotations({
173362
+ description: "Issue identifier (e.g., 'HULY-123')"
173363
+ }),
173364
+ ...FileSourceFields
173365
+ });
173366
+ var AddIssueAttachmentParamsSchema = AddIssueAttachmentParamsBase.pipe(
173367
+ Schema_exports.filter(hasFileSource)
173368
+ ).annotations({
173369
+ title: "AddIssueAttachmentParams",
173370
+ description: "Parameters for adding an attachment to an issue"
173371
+ });
173372
+ var AddDocumentAttachmentParamsBase = Schema_exports.Struct({
173373
+ teamspace: TeamspaceIdentifier.annotations({
173374
+ description: "Teamspace name or ID"
173375
+ }),
173376
+ document: DocumentIdentifier.annotations({
173377
+ description: "Document title or ID"
173378
+ }),
173379
+ ...FileSourceFields
173380
+ });
173381
+ var AddDocumentAttachmentParamsSchema = AddDocumentAttachmentParamsBase.pipe(
173382
+ Schema_exports.filter(hasFileSource)
173383
+ ).annotations({
173384
+ title: "AddDocumentAttachmentParams",
173385
+ description: "Parameters for adding an attachment to a document"
173386
+ });
173387
+ var listAttachmentsParamsJsonSchema = JSONSchema_exports.make(ListAttachmentsParamsSchema);
173388
+ var getAttachmentParamsJsonSchema = JSONSchema_exports.make(GetAttachmentParamsSchema);
173389
+ var addAttachmentParamsJsonSchema = JSONSchema_exports.make(AddAttachmentParamsSchema);
173390
+ var updateAttachmentParamsJsonSchema = JSONSchema_exports.make(UpdateAttachmentParamsSchema);
173391
+ var deleteAttachmentParamsJsonSchema = JSONSchema_exports.make(DeleteAttachmentParamsSchema);
173392
+ var pinAttachmentParamsJsonSchema = JSONSchema_exports.make(PinAttachmentParamsSchema);
173393
+ var downloadAttachmentParamsJsonSchema = JSONSchema_exports.make(DownloadAttachmentParamsSchema);
173394
+ var addIssueAttachmentParamsJsonSchema = JSONSchema_exports.make(AddIssueAttachmentParamsSchema);
173395
+ var addDocumentAttachmentParamsJsonSchema = JSONSchema_exports.make(AddDocumentAttachmentParamsSchema);
173396
+ var parseListAttachmentsParams = Schema_exports.decodeUnknown(ListAttachmentsParamsSchema);
173397
+ var parseGetAttachmentParams = Schema_exports.decodeUnknown(GetAttachmentParamsSchema);
173398
+ var parseAddAttachmentParams = Schema_exports.decodeUnknown(AddAttachmentParamsSchema);
173399
+ var parseUpdateAttachmentParams = Schema_exports.decodeUnknown(UpdateAttachmentParamsSchema);
173400
+ var parseDeleteAttachmentParams = Schema_exports.decodeUnknown(DeleteAttachmentParamsSchema);
173401
+ var parsePinAttachmentParams = Schema_exports.decodeUnknown(PinAttachmentParamsSchema);
173402
+ var parseDownloadAttachmentParams = Schema_exports.decodeUnknown(DownloadAttachmentParamsSchema);
173403
+ var parseAddIssueAttachmentParams = Schema_exports.decodeUnknown(AddIssueAttachmentParamsSchema);
173404
+ var parseAddDocumentAttachmentParams = Schema_exports.decodeUnknown(AddDocumentAttachmentParamsSchema);
173282
173405
 
173283
173406
  // src/huly/operations/attachments.ts
173407
+ var import_core23 = __toESM(require_lib4(), 1);
173284
173408
  var clearAttachmentDescription = (ops) => {
173285
173409
  Object.assign(ops, { description: "" });
173286
173410
  };
@@ -177035,6 +177159,7 @@ var RemoveIssueRelationResultSchema = Schema_exports.Struct({
177035
177159
  });
177036
177160
  var ListIssueRelationsResultSchema = Schema_exports.Struct({
177037
177161
  blockedBy: Schema_exports.Array(RelationEntryWireSchema),
177162
+ blocks: Schema_exports.Array(RelationEntryWireSchema),
177038
177163
  relations: Schema_exports.Array(RelationEntryWireSchema),
177039
177164
  documents: Schema_exports.Array(DocumentRelationEntryWireSchema)
177040
177165
  });
@@ -180719,9 +180844,6 @@ var listIssueRelations = (params) => Effect_exports.gen(function* () {
180719
180844
  });
180720
180845
  const blockedByRefs = issue2.blockedBy ?? [];
180721
180846
  const relationsRefs = issue2.relations ?? [];
180722
- if (blockedByRefs.length === 0 && relationsRefs.length === 0) {
180723
- return { blockedBy: [], relations: [], documents: [] };
180724
- }
180725
180847
  const docClass = String(documentPlugin.class.Document);
180726
180848
  const issueRelationsRefs = [];
180727
180849
  const docRelationsRefs = [];
@@ -180746,6 +180868,16 @@ var listIssueRelations = (params) => Effect_exports.gen(function* () {
180746
180868
  _id: toIssueId(String(r._id)),
180747
180869
  _class: toObjectClassName(String(r._class))
180748
180870
  });
180871
+ const toIssueEntry = (i) => ({
180872
+ identifier: toIssueIdentifier(i.identifier),
180873
+ _id: toIssueId(String(i._id)),
180874
+ _class: toObjectClassName(String(i._class))
180875
+ });
180876
+ const blockingIssueCandidates = yield* client.findAll(
180877
+ tracker.class.Issue,
180878
+ { "blockedBy._id": toRef(issue2._id) }
180879
+ );
180880
+ const blocks = blockingIssueCandidates.filter((candidate) => candidate._id !== issue2._id && hasRelationById(candidate.blockedBy, issue2._id)).map(toIssueEntry);
180749
180881
  const documents = [];
180750
180882
  if (docRelationsRefs.length > 0) {
180751
180883
  const toDocRef = toRef;
@@ -180779,6 +180911,7 @@ var listIssueRelations = (params) => Effect_exports.gen(function* () {
180779
180911
  }
180780
180912
  return {
180781
180913
  blockedBy: blockedByRefs.map(toEntry),
180914
+ blocks,
180782
180915
  relations: issueRelationsRefs.map(toEntry),
180783
180916
  documents
180784
180917
  };
@@ -182244,7 +182377,7 @@ var issueTools = [
182244
182377
  },
182245
182378
  {
182246
182379
  name: "list_issue_relations",
182247
- description: "List all relations of an issue. Returns blockedBy (issues blocking this one), relations (bidirectional issue links), and documents (linked documents with title/teamspace). Does NOT return issues that this issue blocks \u2014 use list_issue_relations on the target issue to see that.",
182380
+ description: "List all relations of an issue. Returns blockedBy (issues blocking this one), blocks (issues this one blocks), relations (bidirectional issue links), and documents (linked documents with title/teamspace).",
182248
182381
  category: CATEGORY11,
182249
182382
  inputSchema: listIssueRelationsParamsJsonSchema,
182250
182383
  handler: createEncodedToolHandler(