@firfi/huly-mcp 0.30.1 → 0.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/dist/index.cjs +644 -66
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -269,7 +269,7 @@ The roadmap is driven by SDK parity and the project principle that this server s
|
|
|
269
269
|
|
|
270
270
|
Highest-value additions for coding agents:
|
|
271
271
|
|
|
272
|
-
- Generic space follow-ups: role
|
|
272
|
+
- Generic space follow-ups: role/permission definition writes, generic space creation, and module-specific wrappers above the shared space foundation. Generic space metadata, member/owner mutations, and typed-space role member mutations are covered by the shared spaces tools.
|
|
273
273
|
- SDK discovery phase 2: space types, roles, permissions, plugin configuration, sequence metadata, and richer tool hints.
|
|
274
274
|
- Drive follow-ups: drive create/update/delete, item move/rename/delete, adding new versions to existing files, permissions, and comments/activity.
|
|
275
275
|
- Planner/ToDos: personal and project ToDo CRUD, scheduling, complete/reopen, priority, privacy/visibility, and document action items.
|
|
@@ -298,7 +298,7 @@ Planned feature surfaces:
|
|
|
298
298
|
- Chat and communication: direct-message send/update/delete, group DMs, channel member mutations, join/leave/request access, archive/unarchive, star/favorite channels, close/reopen conversations, pinned messages, message attachments, translation, applets, in-message polls, and guest communication settings.
|
|
299
299
|
- Notifications and activity: browser/push subscription internals, provider defaults, UI presenter/viewlet metadata, and activity control/extension metadata.
|
|
300
300
|
- Attachments and media: previews/preview metadata and friendly wrappers for additional object types beyond issue/document.
|
|
301
|
-
- Core schema and workspace administration: attribute/property create/update/delete/hide, enum CRUD/options, sequence management, role
|
|
301
|
+
- Core schema and workspace administration: attribute/property create/update/delete/hide, enum CRUD/options, sequence management, role/permission definition writes, generic space creation, global space admins, integrations registry, invite settings, role capability settings, and workspace setting metadata.
|
|
302
302
|
- Integrations: GitHub repository/project mappings and sync metadata (deferred), Google Calendar connect/configure/sync controls, Bitrix entity/field mappings and sync status, Gmail/email channel messages, Telegram messages, Huly Mail/Mail plugin behavior, AI assistant integration state, and AI bot configuration if server-side APIs expose stable behavior.
|
|
303
303
|
- Templates, rating, support, billing, analytics, views, workbench, and preferences: message templates/categories/fields, document/person rating data blocked by unpublished `@hcengineering/rating` SDK package (#90), support conversations, billing tier/status discovery, onboarding channels, saved filtered views, user view preferences, tabs/widgets/apps, and module preference discovery/update.
|
|
304
304
|
- Document-specific gaps: snapshot restore, backlinks, notes, structured action items/tables, PDF/export, advanced document relationships, and document printing/export once SDK support is safe.
|
|
@@ -489,6 +489,7 @@ SDK upgrade revisit:
|
|
|
489
489
|
| `update_channel` | Update fields on an existing Huly channel. Only provided fields are modified. |
|
|
490
490
|
| `delete_channel` | Permanently delete a Huly channel. This action cannot be undone. For reversible channel lifecycle changes, use archive_channel and unarchive_channel instead. |
|
|
491
491
|
| `list_channel_messages` | List messages in a Huly channel. Returns messages sorted by date (newest first). |
|
|
492
|
+
| `list_external_channel_messages` | List read-only messages for an external Gmail or Telegram channel by channel name or ID. The limit defaults to 50 and is capped at 200. When this build does not include a compatible Huly external-message SDK/model for the requested provider, returns supported=false, an unsupportedReason, and an empty messages array; it never sends, replies, deletes, mutates, or returns fake messages. |
|
|
492
493
|
| `send_channel_message` | Send a message to a Huly channel. Message body supports markdown formatting. |
|
|
493
494
|
| `update_channel_message` | Update a channel message. Only the body can be modified. |
|
|
494
495
|
| `delete_channel_message` | Permanently delete a channel message. This action cannot be undone. |
|
|
@@ -739,6 +740,9 @@ SDK upgrade revisit:
|
|
|
739
740
|
| `add_space_members` | Idempotently add members to an existing Huly space. Members accept account UUID, exact email, or exact person display name and resolve to Huly account UUIDs before replacing the full members array. |
|
|
740
741
|
| `remove_space_members` | Idempotently remove members from an existing Huly space. Members accept account UUID, exact email, or exact person display name and resolve to Huly account UUIDs before replacing the full members array. |
|
|
741
742
|
| `set_space_owners` | Replace owners on an existing Huly space. Owners accept account UUID, exact email, or exact person display name. By default, owners are also ensured in members. |
|
|
743
|
+
| `set_space_role_members` | Replace members assigned to one role on a typed Huly space while preserving all other role assignments. Role accepts a raw role _id or exact role name from the space's SpaceType. Members accept account UUID, exact email, or exact person display name; pass members=[] to clear this role. |
|
|
744
|
+
| `add_space_role_members` | Idempotently add members to one role on a typed Huly space while preserving all other role assignments. Role accepts a raw role _id or exact role name from the space's SpaceType. Members accept account UUID, exact email, or exact person display name. |
|
|
745
|
+
| `remove_space_role_members` | Idempotently remove members from one role on a typed Huly space while preserving all other role assignments. Role accepts a raw role _id or exact role name from the space's SpaceType. Members accept account UUID, exact email, or exact person display name. |
|
|
742
746
|
|
|
743
747
|
### Tag-Categories
|
|
744
748
|
|
package/dist/index.cjs
CHANGED
|
@@ -154570,6 +154570,10 @@ var AmbiguousSpaceTypeMatchSchema = Schema_exports.Struct({
|
|
|
154570
154570
|
name: NonEmptyString2,
|
|
154571
154571
|
targetClass: ObjectClassName
|
|
154572
154572
|
});
|
|
154573
|
+
var AmbiguousSpaceRoleMatchSchema = Schema_exports.Struct({
|
|
154574
|
+
id: RoleId,
|
|
154575
|
+
name: NonEmptyString2
|
|
154576
|
+
});
|
|
154573
154577
|
var SpaceNotFoundError = class extends Schema_exports.TaggedError()(
|
|
154574
154578
|
"SpaceNotFoundError",
|
|
154575
154579
|
{
|
|
@@ -154614,6 +154618,54 @@ var SpaceTypeIdentifierAmbiguousError = class extends Schema_exports.TaggedError
|
|
|
154614
154618
|
return `Space type '${this.identifier}' is ambiguous; use a space type id. Matches: ${details}`;
|
|
154615
154619
|
}
|
|
154616
154620
|
};
|
|
154621
|
+
var SpaceNotTypedError = class extends Schema_exports.TaggedError()(
|
|
154622
|
+
"SpaceNotTypedError",
|
|
154623
|
+
{
|
|
154624
|
+
id: SpaceId,
|
|
154625
|
+
name: NonEmptyString2
|
|
154626
|
+
}
|
|
154627
|
+
) {
|
|
154628
|
+
get message() {
|
|
154629
|
+
return `Space '${this.name}' (${this.id}) is not typed; role members can only be changed on spaces with a SpaceType`;
|
|
154630
|
+
}
|
|
154631
|
+
};
|
|
154632
|
+
var SpaceRoleNotFoundError = class extends Schema_exports.TaggedError()(
|
|
154633
|
+
"SpaceRoleNotFoundError",
|
|
154634
|
+
{
|
|
154635
|
+
identifier: NonEmptyString2,
|
|
154636
|
+
spaceType: SpaceTypeId
|
|
154637
|
+
}
|
|
154638
|
+
) {
|
|
154639
|
+
get message() {
|
|
154640
|
+
return `Role '${this.identifier}' not found in space type '${this.spaceType}'`;
|
|
154641
|
+
}
|
|
154642
|
+
};
|
|
154643
|
+
var SpaceRoleIdentifierAmbiguousError = class extends Schema_exports.TaggedError()(
|
|
154644
|
+
"SpaceRoleIdentifierAmbiguousError",
|
|
154645
|
+
{
|
|
154646
|
+
identifier: NonEmptyString2,
|
|
154647
|
+
spaceType: SpaceTypeId,
|
|
154648
|
+
matches: Schema_exports.Array(AmbiguousSpaceRoleMatchSchema).pipe(Schema_exports.minItems(MIN_AMBIGUOUS_SPACE_MATCHES))
|
|
154649
|
+
}
|
|
154650
|
+
) {
|
|
154651
|
+
get message() {
|
|
154652
|
+
const details = this.matches.map((match16) => `${match16.id} (${match16.name})`).join(", ");
|
|
154653
|
+
return `Role '${this.identifier}' is ambiguous in space type '${this.spaceType}'; use a role id. Matches: ${details}`;
|
|
154654
|
+
}
|
|
154655
|
+
};
|
|
154656
|
+
var SpaceRoleAssignmentsMalformedError = class extends Schema_exports.TaggedError()(
|
|
154657
|
+
"SpaceRoleAssignmentsMalformedError",
|
|
154658
|
+
{
|
|
154659
|
+
space: SpaceId,
|
|
154660
|
+
spaceType: SpaceTypeId,
|
|
154661
|
+
targetClass: ObjectClassName,
|
|
154662
|
+
reason: NonEmptyString2
|
|
154663
|
+
}
|
|
154664
|
+
) {
|
|
154665
|
+
get message() {
|
|
154666
|
+
return `Role assignments for space '${this.space}' and space type '${this.spaceType}' are malformed at '${this.targetClass}': ${this.reason}. Refusing to write role members to avoid access-control data loss.`;
|
|
154667
|
+
}
|
|
154668
|
+
};
|
|
154617
154669
|
|
|
154618
154670
|
// src/huly/errors-test-management.ts
|
|
154619
154671
|
var TestProjectNotFoundError = class extends Schema_exports.TaggedError()(
|
|
@@ -154890,6 +154942,10 @@ var HulyDomainError = Schema_exports.Union(
|
|
|
154890
154942
|
HulyClassNotFoundError,
|
|
154891
154943
|
SpaceNotFoundError,
|
|
154892
154944
|
SpaceIdentifierAmbiguousError,
|
|
154945
|
+
SpaceNotTypedError,
|
|
154946
|
+
SpaceRoleNotFoundError,
|
|
154947
|
+
SpaceRoleIdentifierAmbiguousError,
|
|
154948
|
+
SpaceRoleAssignmentsMalformedError,
|
|
154893
154949
|
SpaceTypeNotFoundError,
|
|
154894
154950
|
SpaceTypeIdentifierAmbiguousError,
|
|
154895
154951
|
TodoNotFoundError,
|
|
@@ -155260,6 +155316,10 @@ var HulyClient = class _HulyClient extends Context_exports.Tag("@hulymcp/HulyCli
|
|
|
155260
155316
|
(client2) => client2.findOne(_class, query, options),
|
|
155261
155317
|
"findOne failed"
|
|
155262
155318
|
),
|
|
155319
|
+
findAllInModel: (_class, query, options) => withClient(
|
|
155320
|
+
(client2) => Promise.resolve(client2.getModel().findAllSync(_class, query, options)),
|
|
155321
|
+
"findAllInModel failed"
|
|
155322
|
+
),
|
|
155263
155323
|
createDoc: (_class, space, attributes, id) => withClient(
|
|
155264
155324
|
(client2) => client2.createDoc(_class, space, attributes, id),
|
|
155265
155325
|
"createDoc failed"
|
|
@@ -155341,6 +155401,7 @@ var HulyClient = class _HulyClient extends Context_exports.Tag("@hulymcp/HulyCli
|
|
|
155341
155401
|
markupUrlConfig: testMarkupUrlConfig,
|
|
155342
155402
|
workbenchUrlConfig: testWorkbenchUrlConfig,
|
|
155343
155403
|
findAll: noopFindAll,
|
|
155404
|
+
findAllInModel: noopFindAll,
|
|
155344
155405
|
findOne: noopFindOne,
|
|
155345
155406
|
createDoc: notImplemented("createDoc"),
|
|
155346
155407
|
updateDoc: notImplemented("updateDoc"),
|
|
@@ -155418,6 +155479,7 @@ var import_api_client3 = __toESM(require_lib20(), 1);
|
|
|
155418
155479
|
// src/huly/operations/sdk-boundary.ts
|
|
155419
155480
|
var toRef = (id) => id;
|
|
155420
155481
|
var toClassRef = (id) => id;
|
|
155482
|
+
var toMixinRef = (id) => id;
|
|
155421
155483
|
var toAccountUuid = (uuid5) => uuid5;
|
|
155422
155484
|
var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
155423
155485
|
var validatePersonUuid = (uuid5) => {
|
|
@@ -165740,11 +165802,14 @@ var McpErrorCode = {
|
|
|
165740
165802
|
InternalError: -32603,
|
|
165741
165803
|
ResourceNotFound: -32002
|
|
165742
165804
|
};
|
|
165743
|
-
var createErrorResponse = (text, errorCode, errorTag) =>
|
|
165744
|
-
|
|
165745
|
-
|
|
165746
|
-
|
|
165747
|
-
|
|
165805
|
+
var createErrorResponse = (text, errorCode, errorTag, warnings = []) => {
|
|
165806
|
+
const warningContent = warnings.length > 0 ? [{ type: "text", text: encodeJsonText({ warnings }) }] : [];
|
|
165807
|
+
return {
|
|
165808
|
+
content: [{ type: "text", text }, ...warningContent],
|
|
165809
|
+
isError: true,
|
|
165810
|
+
_meta: { errorCode, errorTag }
|
|
165811
|
+
};
|
|
165812
|
+
};
|
|
165748
165813
|
var INVALID_PARAMS_TAGS = /* @__PURE__ */ new Set([
|
|
165749
165814
|
"IssueNotFoundError",
|
|
165750
165815
|
"ProjectNotFoundError",
|
|
@@ -165835,6 +165900,9 @@ var INVALID_PARAMS_TAGS = /* @__PURE__ */ new Set([
|
|
|
165835
165900
|
"GenericObjectNotFoundError",
|
|
165836
165901
|
"SpaceNotFoundError",
|
|
165837
165902
|
"SpaceIdentifierAmbiguousError",
|
|
165903
|
+
"SpaceNotTypedError",
|
|
165904
|
+
"SpaceRoleNotFoundError",
|
|
165905
|
+
"SpaceRoleIdentifierAmbiguousError",
|
|
165838
165906
|
"SpaceTypeNotFoundError",
|
|
165839
165907
|
"SpaceTypeIdentifierAmbiguousError",
|
|
165840
165908
|
"DriveNotFoundError",
|
|
@@ -165857,13 +165925,13 @@ var INTERNAL_ERROR_PREFIX = {
|
|
|
165857
165925
|
HulyConnectionError: "Connection error",
|
|
165858
165926
|
HulyAuthError: "Authentication error"
|
|
165859
165927
|
};
|
|
165860
|
-
var mapDomainErrorToMcp = (error2) => {
|
|
165928
|
+
var mapDomainErrorToMcp = (error2, warnings = []) => {
|
|
165861
165929
|
if (INVALID_PARAMS_TAGS.has(error2._tag)) {
|
|
165862
|
-
return createErrorResponse(error2.message, McpErrorCode.InvalidParams);
|
|
165930
|
+
return createErrorResponse(error2.message, McpErrorCode.InvalidParams, void 0, warnings);
|
|
165863
165931
|
}
|
|
165864
165932
|
const prefix = INTERNAL_ERROR_PREFIX[error2._tag];
|
|
165865
165933
|
const message = prefix !== void 0 ? `${prefix}: ${error2.message}` : error2.message;
|
|
165866
|
-
return createErrorResponse(message, McpErrorCode.InternalError, error2._tag);
|
|
165934
|
+
return createErrorResponse(message, McpErrorCode.InternalError, error2._tag, warnings);
|
|
165867
165935
|
};
|
|
165868
165936
|
var formatParseError = (error2) => {
|
|
165869
165937
|
const issues = ParseResult_exports.ArrayFormatter.formatErrorSync(error2);
|
|
@@ -165884,34 +165952,44 @@ var mapParseCauseToMcp = (cause3, toolName) => {
|
|
|
165884
165952
|
}
|
|
165885
165953
|
return createErrorResponse("An unexpected error occurred", McpErrorCode.InternalError);
|
|
165886
165954
|
};
|
|
165887
|
-
var mapDomainCauseToMcp = (cause3) => {
|
|
165955
|
+
var mapDomainCauseToMcp = (cause3, warnings = []) => {
|
|
165888
165956
|
if (Cause_exports.isFailType(cause3)) {
|
|
165889
|
-
return mapDomainErrorToMcp(cause3.error);
|
|
165957
|
+
return mapDomainErrorToMcp(cause3.error, warnings);
|
|
165890
165958
|
}
|
|
165891
165959
|
if (Cause_exports.isDieType(cause3)) {
|
|
165892
|
-
return createErrorResponse("An unexpected error occurred", McpErrorCode.InternalError, "UnexpectedError");
|
|
165960
|
+
return createErrorResponse("An unexpected error occurred", McpErrorCode.InternalError, "UnexpectedError", warnings);
|
|
165893
165961
|
}
|
|
165894
165962
|
const failures3 = Chunk_exports.toArray(Cause_exports.failures(cause3));
|
|
165895
165963
|
if (failures3.length > 0) {
|
|
165896
|
-
return mapDomainErrorToMcp(failures3[0]);
|
|
165964
|
+
return mapDomainErrorToMcp(failures3[0], warnings);
|
|
165897
165965
|
}
|
|
165898
|
-
return createErrorResponse("An unexpected error occurred", McpErrorCode.InternalError);
|
|
165966
|
+
return createErrorResponse("An unexpected error occurred", McpErrorCode.InternalError, void 0, warnings);
|
|
165899
165967
|
};
|
|
165900
165968
|
var encodeJsonText = (value3) => {
|
|
165901
165969
|
const text = JSON.stringify(value3);
|
|
165902
165970
|
return typeof text === "string" ? text : "null";
|
|
165903
165971
|
};
|
|
165904
|
-
var createSuccessResponse = (result) => ({
|
|
165905
|
-
content: [
|
|
165906
|
-
|
|
165972
|
+
var createSuccessResponse = (result, warnings = []) => ({
|
|
165973
|
+
content: [
|
|
165974
|
+
{ type: "text", text: encodeJsonText(result) },
|
|
165975
|
+
...warnings.length > 0 ? [{ type: "text", text: encodeJsonText({ warnings }) }] : []
|
|
165976
|
+
],
|
|
165977
|
+
structuredContent: warnings.length > 0 ? {
|
|
165978
|
+
result,
|
|
165979
|
+
warnings
|
|
165980
|
+
} : {
|
|
165907
165981
|
result
|
|
165908
165982
|
}
|
|
165909
165983
|
});
|
|
165910
165984
|
var createUnknownToolError = (toolName) => createErrorResponse(`Unknown tool: ${toolName}`, McpErrorCode.InvalidParams, "UnknownTool");
|
|
165911
165985
|
var createInvalidParamsError = (message, errorTag) => createErrorResponse(message, McpErrorCode.InvalidParams, errorTag);
|
|
165912
|
-
var toMcpResponse = (response) => {
|
|
165913
|
-
|
|
165914
|
-
|
|
165986
|
+
var toMcpResponse = (response) => response.isError === true ? {
|
|
165987
|
+
content: response.content,
|
|
165988
|
+
isError: true
|
|
165989
|
+
} : {
|
|
165990
|
+
content: response.content,
|
|
165991
|
+
...response.structuredContent === void 0 ? {} : { structuredContent: response.structuredContent },
|
|
165992
|
+
...response.isError === void 0 ? {} : { isError: response.isError }
|
|
165915
165993
|
};
|
|
165916
165994
|
|
|
165917
165995
|
// src/mcp/http-2026-dispatcher.ts
|
|
@@ -166468,6 +166546,28 @@ var StdioServerTransport = class {
|
|
|
166468
166546
|
}
|
|
166469
166547
|
};
|
|
166470
166548
|
|
|
166549
|
+
// src/domain/schemas/tool-warnings.ts
|
|
166550
|
+
var ToolWarningCodeSchema = Schema_exports.Literal(
|
|
166551
|
+
"status_metadata_unresolved",
|
|
166552
|
+
"space_role_assignments_degraded"
|
|
166553
|
+
).annotations({
|
|
166554
|
+
identifier: "ToolWarningCode",
|
|
166555
|
+
title: "ToolWarningCode",
|
|
166556
|
+
description: "Machine-readable code for an agent-visible MCP tool warning."
|
|
166557
|
+
});
|
|
166558
|
+
var StatusMetadataUnresolvedWarningCode = ToolWarningCodeSchema.literals[0];
|
|
166559
|
+
var SpaceRoleAssignmentsDegradedWarningCode = ToolWarningCodeSchema.literals[1];
|
|
166560
|
+
var ToolWarningSchema = Schema_exports.Struct({
|
|
166561
|
+
code: ToolWarningCodeSchema,
|
|
166562
|
+
message: Schema_exports.Trim.pipe(Schema_exports.nonEmptyString()).annotations({
|
|
166563
|
+
description: "LLM-facing explanation of what part of the returned tool payload is degraded and how the agent should interpret it."
|
|
166564
|
+
})
|
|
166565
|
+
}).annotations({
|
|
166566
|
+
identifier: "ToolWarning",
|
|
166567
|
+
title: "ToolWarning",
|
|
166568
|
+
description: "Warning surfaced to an agent when a tool result is intentionally degraded instead of failing."
|
|
166569
|
+
});
|
|
166570
|
+
|
|
166471
166571
|
// src/domain/schemas/recurrence-primitives.ts
|
|
166472
166572
|
var MAX_ZERO_BASED_MONTH_INDEX = 11;
|
|
166473
166573
|
var MAX_MONTH_DAY = 31;
|
|
@@ -166518,9 +166618,13 @@ var clearableText = (description) => Schema_exports.NullOr(Schema_exports.String
|
|
|
166518
166618
|
var limitDescription = (subject) => `Maximum ${subject} to return (default: ${DEFAULT_LIMIT}).`;
|
|
166519
166619
|
var SpacePermissionScopeSchema = Schema_exports.Literal("space", "workspace");
|
|
166520
166620
|
var SpaceMemberIdentifier = NonEmptyString2.pipe(Schema_exports.brand("SpaceMemberIdentifier"));
|
|
166621
|
+
var SpaceRoleIdentifier = NonEmptyString2.pipe(Schema_exports.brand("SpaceRoleIdentifier"));
|
|
166521
166622
|
var SpaceMemberIdentifierSchema = SpaceMemberIdentifier.annotations({
|
|
166522
166623
|
description: "Workspace member to resolve. Accepts a Huly account UUID directly, an exact email address, or an exact person display name."
|
|
166523
166624
|
});
|
|
166625
|
+
var SpaceRoleIdentifierSchema = SpaceRoleIdentifier.annotations({
|
|
166626
|
+
description: "Role to resolve within the space's SpaceType. Accepts a raw Huly role _id or an exact role name from get_space_type."
|
|
166627
|
+
});
|
|
166524
166628
|
var SpaceRoleAssignmentSchema = Schema_exports.Struct({
|
|
166525
166629
|
roleId: RoleId,
|
|
166526
166630
|
members: Schema_exports.Array(AccountUuid)
|
|
@@ -166695,6 +166799,28 @@ var SetSpaceOwnersParamsSchema = Schema_exports.Struct({
|
|
|
166695
166799
|
description: `Also add each owner to members. Defaults to ${DEFAULT_SPACE_OWNER_ENSURE_MEMBERS}.`
|
|
166696
166800
|
}))
|
|
166697
166801
|
});
|
|
166802
|
+
var SpaceRoleMemberMutationFields = {
|
|
166803
|
+
space: SpaceIdentifier.annotations({
|
|
166804
|
+
description: "Typed space _id or exact space name whose role assignment should change. The space must have a SpaceType."
|
|
166805
|
+
}),
|
|
166806
|
+
class: Schema_exports.optional(SpaceClassFilter.annotations({
|
|
166807
|
+
description: "Optional raw Huly space class ID used to disambiguate exact-name lookup."
|
|
166808
|
+
})),
|
|
166809
|
+
type: Schema_exports.optional(SpaceTypeId.annotations({
|
|
166810
|
+
description: "Optional raw Huly SpaceType _id used to disambiguate exact-name lookup."
|
|
166811
|
+
})),
|
|
166812
|
+
role: SpaceRoleIdentifierSchema,
|
|
166813
|
+
members: Schema_exports.Array(SpaceMemberIdentifierSchema).pipe(Schema_exports.minItems(1)).annotations({
|
|
166814
|
+
description: "Members to add or remove from this role. Each entry may be an account UUID, exact email address, or exact person name."
|
|
166815
|
+
})
|
|
166816
|
+
};
|
|
166817
|
+
var SpaceRoleMemberMutationParamsSchema = Schema_exports.Struct(SpaceRoleMemberMutationFields);
|
|
166818
|
+
var SetSpaceRoleMembersParamsSchema = Schema_exports.Struct({
|
|
166819
|
+
...SpaceRoleMemberMutationFields,
|
|
166820
|
+
members: Schema_exports.Array(SpaceMemberIdentifierSchema).annotations({
|
|
166821
|
+
description: "Replacement member list for this role only. Each entry may be an account UUID, exact email address, or exact person name. Pass [] to clear this role."
|
|
166822
|
+
})
|
|
166823
|
+
});
|
|
166698
166824
|
var listSpacesParamsJsonSchema = JSONSchema_exports.make(ListSpacesParamsSchema);
|
|
166699
166825
|
var getSpaceParamsJsonSchema = JSONSchema_exports.make(GetSpaceParamsSchema);
|
|
166700
166826
|
var listSpaceTypesParamsJsonSchema = JSONSchema_exports.make(ListSpaceTypesParamsSchema);
|
|
@@ -166706,6 +166832,8 @@ var updateSpaceParamsJsonSchema = withAtLeastOneRequired(
|
|
|
166706
166832
|
);
|
|
166707
166833
|
var spaceMemberMutationParamsJsonSchema = JSONSchema_exports.make(SpaceMemberMutationParamsSchema);
|
|
166708
166834
|
var setSpaceOwnersParamsJsonSchema = JSONSchema_exports.make(SetSpaceOwnersParamsSchema);
|
|
166835
|
+
var spaceRoleMemberMutationParamsJsonSchema = JSONSchema_exports.make(SpaceRoleMemberMutationParamsSchema);
|
|
166836
|
+
var setSpaceRoleMembersParamsJsonSchema = JSONSchema_exports.make(SetSpaceRoleMembersParamsSchema);
|
|
166709
166837
|
var parseListSpacesParams = Schema_exports.decodeUnknown(ListSpacesParamsSchema);
|
|
166710
166838
|
var parseGetSpaceParams = Schema_exports.decodeUnknown(GetSpaceParamsSchema);
|
|
166711
166839
|
var parseListSpaceTypesParams = Schema_exports.decodeUnknown(ListSpaceTypesParamsSchema);
|
|
@@ -166714,6 +166842,8 @@ var parseListSpacePermissionsParams = Schema_exports.decodeUnknown(ListSpacePerm
|
|
|
166714
166842
|
var parseUpdateSpaceParams = Schema_exports.decodeUnknown(UpdateSpaceParamsSchema);
|
|
166715
166843
|
var parseSpaceMemberMutationParams = Schema_exports.decodeUnknown(SpaceMemberMutationParamsSchema);
|
|
166716
166844
|
var parseSetSpaceOwnersParams = Schema_exports.decodeUnknown(SetSpaceOwnersParamsSchema);
|
|
166845
|
+
var parseSpaceRoleMemberMutationParams = Schema_exports.decodeUnknown(SpaceRoleMemberMutationParamsSchema);
|
|
166846
|
+
var parseSetSpaceRoleMembersParams = Schema_exports.decodeUnknown(SetSpaceRoleMembersParamsSchema);
|
|
166717
166847
|
|
|
166718
166848
|
// src/domain/schemas/sdk-discovery.ts
|
|
166719
166849
|
var import_core10 = __toESM(require_lib4(), 1);
|
|
@@ -167252,6 +167382,7 @@ var ProjectTypeDetailSchema = Schema_exports.Struct({
|
|
|
167252
167382
|
descriptor: NonEmptyString2,
|
|
167253
167383
|
classic: Schema_exports.Boolean,
|
|
167254
167384
|
isDefaultClassic: Schema_exports.Boolean,
|
|
167385
|
+
statusCount: Count,
|
|
167255
167386
|
taskTypes: Schema_exports.Array(TaskTypeSummarySchema),
|
|
167256
167387
|
statuses: Schema_exports.Array(IssueStatusSummarySchema),
|
|
167257
167388
|
statusCategories: Schema_exports.Array(StatusCategorySummarySchema),
|
|
@@ -170099,6 +170230,91 @@ var parseUpdatePersonParams = Schema_exports.decodeUnknown(UpdatePersonParamsSch
|
|
|
170099
170230
|
var parseDeletePersonParams = Schema_exports.decodeUnknown(DeletePersonParamsSchema);
|
|
170100
170231
|
var parseListEmployeesParams = Schema_exports.decodeUnknown(ListEmployeesParamsSchema);
|
|
170101
170232
|
|
|
170233
|
+
// src/domain/schemas/external-channel-messages.ts
|
|
170234
|
+
var ExternalChannelMessageProviderValues = ["gmail", "telegram"];
|
|
170235
|
+
var ExternalChannelMessageProviderSchema = Schema_exports.Literal(...ExternalChannelMessageProviderValues);
|
|
170236
|
+
var DEFAULT_EXTERNAL_CHANNEL_MESSAGE_LIMIT = DEFAULT_LIMIT;
|
|
170237
|
+
var ListExternalChannelMessagesParamsSchema = Schema_exports.Struct({
|
|
170238
|
+
provider: ExternalChannelMessageProviderSchema.annotations({
|
|
170239
|
+
description: "External provider to read from. Supported locator values are validated for gmail and telegram; providers without a compatible installed Huly message SDK return structured unsupported results instead of fake data."
|
|
170240
|
+
}),
|
|
170241
|
+
channel: ChannelIdentifier.annotations({
|
|
170242
|
+
description: "External channel name or Huly channel ID locator, such as a Gmail label/inbox name or Telegram chat name/id."
|
|
170243
|
+
}),
|
|
170244
|
+
limit: Schema_exports.optional(LimitParam.annotations({
|
|
170245
|
+
description: `Maximum number of external messages to return (default: ${DEFAULT_EXTERNAL_CHANNEL_MESSAGE_LIMIT}, max: 200).`
|
|
170246
|
+
}))
|
|
170247
|
+
}).annotations({
|
|
170248
|
+
title: "ListExternalChannelMessagesParams",
|
|
170249
|
+
description: "Parameters for listing read-only Gmail or Telegram external channel messages."
|
|
170250
|
+
});
|
|
170251
|
+
var ExternalChannelMessageId = NonEmptyString2.pipe(Schema_exports.brand("ExternalChannelMessageId")).annotations({
|
|
170252
|
+
identifier: "ExternalChannelMessageId",
|
|
170253
|
+
title: "ExternalChannelMessageId",
|
|
170254
|
+
description: "Opaque external provider message ID."
|
|
170255
|
+
});
|
|
170256
|
+
var ExternalChannelMessageSubject = NonEmptyString2.pipe(
|
|
170257
|
+
Schema_exports.brand("ExternalChannelMessageSubject")
|
|
170258
|
+
).annotations({
|
|
170259
|
+
identifier: "ExternalChannelMessageSubject",
|
|
170260
|
+
title: "ExternalChannelMessageSubject",
|
|
170261
|
+
description: "Non-empty external message subject. Omit the field when the provider has no subject value."
|
|
170262
|
+
});
|
|
170263
|
+
var ExternalChannelMessageSender = NonEmptyString2.pipe(Schema_exports.brand("ExternalChannelMessageSender")).annotations({
|
|
170264
|
+
identifier: "ExternalChannelMessageSender",
|
|
170265
|
+
title: "ExternalChannelMessageSender",
|
|
170266
|
+
description: "Non-empty normalized external message sender label or address."
|
|
170267
|
+
});
|
|
170268
|
+
var ExternalChannelMessageSenderId = NonEmptyString2.pipe(Schema_exports.brand("ExternalChannelMessageSenderId")).annotations({
|
|
170269
|
+
identifier: "ExternalChannelMessageSenderId",
|
|
170270
|
+
title: "ExternalChannelMessageSenderId",
|
|
170271
|
+
description: "Non-empty opaque external provider sender ID."
|
|
170272
|
+
});
|
|
170273
|
+
var ExternalChannelMessageSummarySchema = Schema_exports.Struct({
|
|
170274
|
+
id: ExternalChannelMessageId,
|
|
170275
|
+
subject: Schema_exports.optional(ExternalChannelMessageSubject),
|
|
170276
|
+
bodyPreview: NonEmptyString2,
|
|
170277
|
+
sender: Schema_exports.optional(ExternalChannelMessageSender),
|
|
170278
|
+
senderId: Schema_exports.optional(ExternalChannelMessageSenderId),
|
|
170279
|
+
createdOn: Schema_exports.optional(Timestamp),
|
|
170280
|
+
modifiedOn: Schema_exports.optional(Timestamp),
|
|
170281
|
+
url: Schema_exports.optional(UrlString)
|
|
170282
|
+
}).annotations({
|
|
170283
|
+
title: "ExternalChannelMessageSummary",
|
|
170284
|
+
description: "Normalized read-only summary of one external Gmail or Telegram message."
|
|
170285
|
+
});
|
|
170286
|
+
var ListExternalChannelMessagesSupportedResultSchema = Schema_exports.Struct({
|
|
170287
|
+
supported: Schema_exports.Literal(true),
|
|
170288
|
+
provider: ExternalChannelMessageProviderSchema,
|
|
170289
|
+
channel: ChannelIdentifier,
|
|
170290
|
+
limit: LimitParam,
|
|
170291
|
+
messages: Schema_exports.Array(ExternalChannelMessageSummarySchema)
|
|
170292
|
+
}).annotations({
|
|
170293
|
+
title: "ListExternalChannelMessagesSupportedResult",
|
|
170294
|
+
description: "External channel messages returned from a compatible installed Huly provider SDK/model."
|
|
170295
|
+
});
|
|
170296
|
+
var ListExternalChannelMessagesUnsupportedResultSchema = Schema_exports.Struct({
|
|
170297
|
+
supported: Schema_exports.Literal(false),
|
|
170298
|
+
provider: ExternalChannelMessageProviderSchema,
|
|
170299
|
+
channel: ChannelIdentifier,
|
|
170300
|
+
limit: LimitParam,
|
|
170301
|
+
unsupportedReason: NonEmptyString2,
|
|
170302
|
+
messages: Schema_exports.Tuple()
|
|
170303
|
+
}).annotations({
|
|
170304
|
+
title: "ListExternalChannelMessagesUnsupportedResult",
|
|
170305
|
+
description: "Explicit no-fake-data result when the requested external provider cannot be read in this build."
|
|
170306
|
+
});
|
|
170307
|
+
var ListExternalChannelMessagesResultSchema = Schema_exports.Union(
|
|
170308
|
+
ListExternalChannelMessagesSupportedResultSchema,
|
|
170309
|
+
ListExternalChannelMessagesUnsupportedResultSchema
|
|
170310
|
+
).annotations({
|
|
170311
|
+
title: "ListExternalChannelMessagesResult",
|
|
170312
|
+
description: "Read-only external channel message listing result."
|
|
170313
|
+
});
|
|
170314
|
+
var listExternalChannelMessagesParamsJsonSchema = JSONSchema_exports.make(ListExternalChannelMessagesParamsSchema);
|
|
170315
|
+
var parseListExternalChannelMessagesParams = Schema_exports.decodeUnknown(ListExternalChannelMessagesParamsSchema);
|
|
170316
|
+
var encodeListExternalChannelMessagesResult = Schema_exports.encodeSync(ListExternalChannelMessagesResultSchema);
|
|
170317
|
+
|
|
170102
170318
|
// src/domain/schemas/channels.ts
|
|
170103
170319
|
var ListChannelsParamsBase = Schema_exports.Struct({
|
|
170104
170320
|
nameSearch: Schema_exports.optional(Schema_exports.String.annotations({
|
|
@@ -174502,15 +174718,52 @@ var parseUpdateDriveFileCommentParams = Schema_exports.decodeUnknown(UpdateDrive
|
|
|
174502
174718
|
var parseDeleteDriveFileCommentParams = Schema_exports.decodeUnknown(DeleteDriveFileCommentParamsSchema);
|
|
174503
174719
|
var parseListDriveFileActivityParams = Schema_exports.decodeUnknown(ListDriveFileActivityParamsSchema);
|
|
174504
174720
|
|
|
174721
|
+
// src/huly/diagnostics.ts
|
|
174722
|
+
var Diagnostics = class extends Context_exports.Tag("@hulymcp/Diagnostics")() {
|
|
174723
|
+
};
|
|
174724
|
+
var warningLogText = (warning) => `Agent-visible tool warning [${warning.code}]: ${warning.message}`;
|
|
174725
|
+
var makeDiagnosticsScope = Effect_exports.gen(function* () {
|
|
174726
|
+
const warningsRef = yield* Ref_exports.make([]);
|
|
174727
|
+
return {
|
|
174728
|
+
service: {
|
|
174729
|
+
warnAgent: (warning) => Ref_exports.update(warningsRef, (warnings) => [...warnings, warning]).pipe(
|
|
174730
|
+
Effect_exports.zipRight(Effect_exports.logWarning(warningLogText(warning)))
|
|
174731
|
+
),
|
|
174732
|
+
trail: (message) => Effect_exports.logInfo(`Diagnostic trail: ${message}`)
|
|
174733
|
+
},
|
|
174734
|
+
drainWarnings: Ref_exports.get(warningsRef)
|
|
174735
|
+
};
|
|
174736
|
+
});
|
|
174737
|
+
|
|
174505
174738
|
// src/version.ts
|
|
174506
|
-
var VERSION = true ? "0.
|
|
174739
|
+
var VERSION = true ? "0.31.1" : "0.0.0-dev";
|
|
174507
174740
|
|
|
174508
174741
|
// src/mcp/tool-output-schema.ts
|
|
174742
|
+
var toolWarningCodeEnum = [...ToolWarningCodeSchema.literals];
|
|
174509
174743
|
var defaultToolOutputSchema = {
|
|
174510
174744
|
type: "object",
|
|
174511
174745
|
properties: {
|
|
174512
174746
|
result: {
|
|
174513
174747
|
description: "The successful tool result. The same value is also serialized as JSON in the text content for clients that do not read structuredContent."
|
|
174748
|
+
},
|
|
174749
|
+
warnings: {
|
|
174750
|
+
type: "array",
|
|
174751
|
+
description: "Optional agent-visible warnings about degraded result fidelity. Omitted when the server returned the documented happy-path payload.",
|
|
174752
|
+
items: {
|
|
174753
|
+
type: "object",
|
|
174754
|
+
properties: {
|
|
174755
|
+
code: {
|
|
174756
|
+
type: "string",
|
|
174757
|
+
enum: toolWarningCodeEnum
|
|
174758
|
+
},
|
|
174759
|
+
message: {
|
|
174760
|
+
type: "string",
|
|
174761
|
+
minLength: 1
|
|
174762
|
+
}
|
|
174763
|
+
},
|
|
174764
|
+
required: ["code", "message"],
|
|
174765
|
+
additionalProperties: false
|
|
174766
|
+
}
|
|
174514
174767
|
}
|
|
174515
174768
|
},
|
|
174516
174769
|
required: ["result"]
|
|
@@ -174983,6 +175236,93 @@ var removeAccountUuids = (current, removals) => {
|
|
|
174983
175236
|
var arraysEqual = (left3, right3) => left3.length === right3.length && left3.every((value3, index) => value3 === right3[index]);
|
|
174984
175237
|
var optionalString = (value3) => value3 === void 0 || value3 === "" ? void 0 : value3;
|
|
174985
175238
|
var optionalObjectClassName = (value3) => value3 === void 0 || value3 === "" ? void 0 : ObjectClassName.make(value3);
|
|
175239
|
+
var RoleAssignmentStorageSchema = Schema_exports.Record({ key: Schema_exports.String, value: Schema_exports.Array(AccountUuid) });
|
|
175240
|
+
var isRecordObject = (value3) => typeof value3 === "object" && value3 !== null && !Array.isArray(value3);
|
|
175241
|
+
var validStoredAccountUuid = (value3) => {
|
|
175242
|
+
const decoded = Schema_exports.decodeUnknownEither(AccountUuid)(value3);
|
|
175243
|
+
return decoded._tag === "Right" ? toAccountUuid(NonEmptyString2.make(decoded.right)) : void 0;
|
|
175244
|
+
};
|
|
175245
|
+
var parsedSpaceRoleAssignmentEntry = (roleId, members) => ({
|
|
175246
|
+
_tag: "entry",
|
|
175247
|
+
entry: [
|
|
175248
|
+
toRef(roleId),
|
|
175249
|
+
sortStrings(members).map(toAccountUuid)
|
|
175250
|
+
]
|
|
175251
|
+
});
|
|
175252
|
+
var spaceRoleAssignmentSource = (space, spaceType) => Object.prototype.hasOwnProperty.call(space, spaceType.targetClass) ? { present: true, value: Object.entries(space).find(([key]) => key === spaceType.targetClass)?.[1] } : { present: false, value: void 0 };
|
|
175253
|
+
var roleAssignmentsMalformedError = (space, spaceType, reason) => new SpaceRoleAssignmentsMalformedError({
|
|
175254
|
+
space: SpaceId.make(space._id),
|
|
175255
|
+
spaceType: SpaceTypeId.make(spaceType._id),
|
|
175256
|
+
targetClass: ObjectClassName.make(spaceType.targetClass),
|
|
175257
|
+
reason: NonEmptyString2.make(reason)
|
|
175258
|
+
});
|
|
175259
|
+
var readSpaceRoleAssignmentEntries = (space, spaceType, validRoleIds) => {
|
|
175260
|
+
const source = spaceRoleAssignmentSource(space, spaceType);
|
|
175261
|
+
if (!source.present) return { entries: [], degradationReasons: [] };
|
|
175262
|
+
if (!isRecordObject(source.value)) {
|
|
175263
|
+
return {
|
|
175264
|
+
entries: [],
|
|
175265
|
+
degradationReasons: [`role assignment mixin ${spaceType.targetClass} is not an object`]
|
|
175266
|
+
};
|
|
175267
|
+
}
|
|
175268
|
+
const parsed = Object.entries(source.value).flatMap(([roleId, members]) => {
|
|
175269
|
+
if (!validRoleIds.has(toRef(roleId))) {
|
|
175270
|
+
return [{
|
|
175271
|
+
_tag: "dropped",
|
|
175272
|
+
reason: `role assignment '${roleId}' is not defined on space type ${spaceType._id}`
|
|
175273
|
+
}];
|
|
175274
|
+
}
|
|
175275
|
+
if (!Array.isArray(members)) {
|
|
175276
|
+
return [{ _tag: "dropped", reason: `role assignment '${roleId}' members are not an array` }];
|
|
175277
|
+
}
|
|
175278
|
+
const accountUuids = members.flatMap((member) => {
|
|
175279
|
+
const accountUuid = validStoredAccountUuid(member);
|
|
175280
|
+
return accountUuid === void 0 ? [] : [accountUuid];
|
|
175281
|
+
});
|
|
175282
|
+
const invalidMemberCount = members.length - accountUuids.length;
|
|
175283
|
+
return [
|
|
175284
|
+
...invalidMemberCount > 0 ? [{
|
|
175285
|
+
_tag: "dropped",
|
|
175286
|
+
reason: `role assignment '${roleId}' has ${invalidMemberCount} malformed account UUID value(s)`
|
|
175287
|
+
}] : [],
|
|
175288
|
+
parsedSpaceRoleAssignmentEntry(roleId, accountUuids)
|
|
175289
|
+
];
|
|
175290
|
+
});
|
|
175291
|
+
return {
|
|
175292
|
+
entries: parsed.flatMap((item) => item._tag === "entry" ? [item.entry] : []),
|
|
175293
|
+
degradationReasons: parsed.flatMap((item) => item._tag === "dropped" ? [item.reason] : [])
|
|
175294
|
+
};
|
|
175295
|
+
};
|
|
175296
|
+
var spaceRoleAssignmentEntries = (space, spaceType, validRoleIds) => readSpaceRoleAssignmentEntries(space, spaceType, validRoleIds).entries;
|
|
175297
|
+
var hasSpaceRoleAssignmentMixin = (space, spaceType) => spaceRoleAssignmentSource(space, spaceType).present;
|
|
175298
|
+
var strictSpaceRoleAssignments = (space, spaceType, validRoleIds) => Effect_exports.gen(function* () {
|
|
175299
|
+
const source = spaceRoleAssignmentSource(space, spaceType);
|
|
175300
|
+
if (!source.present) return {};
|
|
175301
|
+
const decoded = Schema_exports.decodeUnknownEither(RoleAssignmentStorageSchema)(source.value);
|
|
175302
|
+
if (decoded._tag === "Left") {
|
|
175303
|
+
return yield* roleAssignmentsMalformedError(
|
|
175304
|
+
space,
|
|
175305
|
+
spaceType,
|
|
175306
|
+
`expected an object whose keys are role ids and values are arrays of account UUIDs`
|
|
175307
|
+
);
|
|
175308
|
+
}
|
|
175309
|
+
const unknownRoleIds = Object.keys(decoded.right).filter((roleId) => !validRoleIds.has(toRef(roleId)));
|
|
175310
|
+
if (unknownRoleIds.length > 0) {
|
|
175311
|
+
return yield* roleAssignmentsMalformedError(
|
|
175312
|
+
space,
|
|
175313
|
+
spaceType,
|
|
175314
|
+
`unknown role assignment key(s): ${unknownRoleIds.join(", ")}`
|
|
175315
|
+
);
|
|
175316
|
+
}
|
|
175317
|
+
return Object.fromEntries(
|
|
175318
|
+
Object.entries(decoded.right).map(([roleId, members]) => [
|
|
175319
|
+
toRef(roleId),
|
|
175320
|
+
members.map((member) => toAccountUuid(NonEmptyString2.make(member)))
|
|
175321
|
+
])
|
|
175322
|
+
);
|
|
175323
|
+
});
|
|
175324
|
+
var roleAssignmentDegradationMessage = (reasons) => `Some typed-space role assignment data was omitted because existing Huly storage is malformed: ${reasons.join("; ")}. Read results include only valid role assignments; role-member write tools will refuse to modify this space until the stored role assignment data is repaired.`;
|
|
175325
|
+
var spaceRoleAssignmentsMixin = (spaceType) => toMixinRef(spaceType.targetClass);
|
|
174986
175326
|
var applySpaceFilters = (query, filters) => {
|
|
174987
175327
|
const next4 = { ...query };
|
|
174988
175328
|
if (!filters.includeArchived) {
|
|
@@ -176182,7 +176522,7 @@ var findProject = (projectIdentifier) => Effect_exports.gen(function* () {
|
|
|
176182
176522
|
);
|
|
176183
176523
|
return { client, project: project3 };
|
|
176184
176524
|
});
|
|
176185
|
-
var statusCategoryValueFromRef = (category) => category === void 0 ?
|
|
176525
|
+
var statusCategoryValueFromRef = (category) => category === void 0 ? UnknownStatusCategoryValue : StatusCategoryEntries.find((entry) => entry.ref === category)?.key ?? UnknownStatusCategoryValue;
|
|
176186
176526
|
var workflowStatusFromDoc = (doc) => {
|
|
176187
176527
|
return {
|
|
176188
176528
|
_id: doc._id,
|
|
@@ -176195,7 +176535,7 @@ var workflowStatusFromRef = (statusRef) => {
|
|
|
176195
176535
|
return {
|
|
176196
176536
|
_id: statusRef,
|
|
176197
176537
|
name,
|
|
176198
|
-
category:
|
|
176538
|
+
category: UnknownStatusCategoryValue
|
|
176199
176539
|
};
|
|
176200
176540
|
};
|
|
176201
176541
|
var uniqueStatusRefs = (refs) => refs.reduce(
|
|
@@ -176207,6 +176547,51 @@ var uniqueStatusDocs = (statuses) => Array.from(statuses).reduce(
|
|
|
176207
176547
|
[]
|
|
176208
176548
|
);
|
|
176209
176549
|
var uniqueProjectTypeStatusRefs = (statuses) => uniqueStatusRefs(statuses.map((status) => status._id));
|
|
176550
|
+
var missingStatusRefs = (statusRefs, statusDocs) => statusRefs.filter((statusRef) => !statusDocs.some((statusDoc) => statusDoc._id === statusRef));
|
|
176551
|
+
var resolveByStatusRef = (statusRefs, statusDocs, fromDoc, fromRef) => {
|
|
176552
|
+
const statusDocsById = new Map(statusDocs.map((statusDoc) => [statusDoc._id, statusDoc]));
|
|
176553
|
+
return statusRefs.map((statusRef) => {
|
|
176554
|
+
const statusDoc = statusDocsById.get(statusRef);
|
|
176555
|
+
return statusDoc === void 0 ? fromRef(statusRef) : fromDoc(statusDoc);
|
|
176556
|
+
});
|
|
176557
|
+
};
|
|
176558
|
+
var workflowStatusesFromDocsOrRefs = (statusRefs, statusDocs) => resolveByStatusRef(statusRefs, statusDocs, workflowStatusFromDoc, workflowStatusFromRef);
|
|
176559
|
+
var findStatusDocs = (client, statusRefs) => Effect_exports.gen(function* () {
|
|
176560
|
+
const diagnostics = yield* Diagnostics;
|
|
176561
|
+
const remoteResult = yield* Effect_exports.either(
|
|
176562
|
+
client.findAll(
|
|
176563
|
+
core.class.Status,
|
|
176564
|
+
hulyQuery({ _id: { $in: [...statusRefs] } })
|
|
176565
|
+
)
|
|
176566
|
+
);
|
|
176567
|
+
const remoteDocs = remoteResult._tag === "Right" ? uniqueStatusDocs(remoteResult.right) : [];
|
|
176568
|
+
const unresolvedRefs = missingStatusRefs(statusRefs, remoteDocs);
|
|
176569
|
+
if (unresolvedRefs.length === 0) {
|
|
176570
|
+
return remoteDocs;
|
|
176571
|
+
}
|
|
176572
|
+
const modelResult = yield* Effect_exports.either(
|
|
176573
|
+
client.findAllInModel(
|
|
176574
|
+
core.class.Status,
|
|
176575
|
+
hulyQuery({ _id: { $in: unresolvedRefs } })
|
|
176576
|
+
)
|
|
176577
|
+
);
|
|
176578
|
+
const modelDocs = modelResult._tag === "Right" ? uniqueStatusDocs(modelResult.right) : [];
|
|
176579
|
+
const combinedDocs = uniqueStatusDocs([...remoteDocs, ...modelDocs]);
|
|
176580
|
+
const stillUnresolvedRefs = missingStatusRefs(statusRefs, combinedDocs);
|
|
176581
|
+
if (stillUnresolvedRefs.length > 0) {
|
|
176582
|
+
const remoteError = remoteResult._tag === "Left" ? ` Remote error: ${remoteResult.left.message}` : "";
|
|
176583
|
+
const modelError = modelResult._tag === "Left" ? ` Model error: ${modelResult.left.message}` : "";
|
|
176584
|
+
yield* diagnostics.warnAgent({
|
|
176585
|
+
code: StatusMetadataUnresolvedWarningCode,
|
|
176586
|
+
message: `Huly did not return metadata for ${stillUnresolvedRefs.length} workflow status ref(s). The tool result uses ref-derived status names and category "${UnknownStatusCategoryValue}" for those statuses; do not infer completion or cancellation semantics from those fallback names.${remoteError}${modelError}`
|
|
176587
|
+
});
|
|
176588
|
+
} else if (remoteResult._tag === "Left") {
|
|
176589
|
+
yield* diagnostics.trail(
|
|
176590
|
+
`Server status metadata lookup failed, but the local Huly model resolved all requested workflow statuses. Remote error: ${remoteResult.left.message}`
|
|
176591
|
+
);
|
|
176592
|
+
}
|
|
176593
|
+
return combinedDocs;
|
|
176594
|
+
});
|
|
176210
176595
|
var findProjectWithStatuses = (projectIdentifier) => Effect_exports.gen(function* () {
|
|
176211
176596
|
const client = yield* HulyClient;
|
|
176212
176597
|
const project3 = yield* findOneOrFail(
|
|
@@ -176222,19 +176607,8 @@ var findProjectWithStatuses = (projectIdentifier) => Effect_exports.gen(function
|
|
|
176222
176607
|
if (statusRefs.length === 0) {
|
|
176223
176608
|
return [];
|
|
176224
176609
|
}
|
|
176225
|
-
const
|
|
176226
|
-
|
|
176227
|
-
core.class.Status,
|
|
176228
|
-
hulyQuery({ _id: { $in: statusRefs } })
|
|
176229
|
-
)
|
|
176230
|
-
);
|
|
176231
|
-
if (statusDocsResult._tag === "Right") {
|
|
176232
|
-
return uniqueStatusDocs(statusDocsResult.right).map(workflowStatusFromDoc);
|
|
176233
|
-
}
|
|
176234
|
-
yield* Effect_exports.logWarning(
|
|
176235
|
-
`Status query failed for project ${projectIdentifier}, using fallback. statusCategory filtering is unavailable until Huly returns status metadata. Error: ${statusDocsResult.left.message}`
|
|
176236
|
-
);
|
|
176237
|
-
return statusRefs.map(workflowStatusFromRef);
|
|
176610
|
+
const statusDocs = yield* findStatusDocs(client, statusRefs);
|
|
176611
|
+
return workflowStatusesFromDocsOrRefs(statusRefs, statusDocs);
|
|
176238
176612
|
}) : [];
|
|
176239
176613
|
const defaultStatusId = project3.defaultIssueStatus || statuses[0]?._id;
|
|
176240
176614
|
return { client, defaultStatusId, project: project3, projectType, statuses };
|
|
@@ -176598,19 +176972,27 @@ var createHandler = (toolName, provide4, parse5, operation, encode8) => async (a
|
|
|
176598
176972
|
if (Exit_exports.isFailure(parseResult)) {
|
|
176599
176973
|
return mapParseCauseToMcp(parseResult.cause, toolName);
|
|
176600
176974
|
}
|
|
176601
|
-
const
|
|
176975
|
+
const diagnosticsScope = await Effect_exports.runPromise(makeDiagnosticsScope);
|
|
176976
|
+
const provided = provide4({
|
|
176977
|
+
hulyClient,
|
|
176978
|
+
storageClient,
|
|
176979
|
+
workspaceClient
|
|
176980
|
+
})(operation(parseResult.value));
|
|
176602
176981
|
if (Either_exports.isLeft(provided)) {
|
|
176603
176982
|
return provided.left;
|
|
176604
176983
|
}
|
|
176605
|
-
const operationResult = await Effect_exports.runPromiseExit(
|
|
176984
|
+
const operationResult = await Effect_exports.runPromiseExit(
|
|
176985
|
+
provided.right.pipe(Effect_exports.provideService(Diagnostics, diagnosticsScope.service))
|
|
176986
|
+
);
|
|
176987
|
+
const warnings = await Effect_exports.runPromise(diagnosticsScope.drainWarnings);
|
|
176606
176988
|
if (Exit_exports.isFailure(operationResult)) {
|
|
176607
|
-
return mapDomainCauseToMcp(operationResult.cause);
|
|
176989
|
+
return mapDomainCauseToMcp(operationResult.cause, warnings);
|
|
176608
176990
|
}
|
|
176609
176991
|
try {
|
|
176610
176992
|
const output = encode8 !== void 0 ? encode8(operationResult.value) : operationResult.value;
|
|
176611
|
-
return createSuccessResponse(output);
|
|
176993
|
+
return createSuccessResponse(output, warnings);
|
|
176612
176994
|
} catch {
|
|
176613
|
-
return mapDomainErrorToMcp(new HulyError({ message: `Tool ${toolName} produced invalid output` }));
|
|
176995
|
+
return mapDomainErrorToMcp(new HulyError({ message: `Tool ${toolName} produced invalid output` }), warnings);
|
|
176614
176996
|
}
|
|
176615
176997
|
};
|
|
176616
176998
|
var createToolHandler = (toolName, parse5, operation) => createHandler(toolName, provideHulyClient, parse5, operation);
|
|
@@ -178722,7 +179104,7 @@ var contactCoveredRationale = "Current contacts tools expose person, organizatio
|
|
|
178722
179104
|
var cardCoveredRationale = "Current card tools cover card spaces, master tags, and card CRUD.";
|
|
178723
179105
|
var chunterCoveredRationale = "Current channel and direct-message tools cover channels, channel messages, one-to-one DM listing, and thread replies.";
|
|
178724
179106
|
var coreCoveredRationale = "Existing tools expose user statuses, full-text search, blobs through storage/download flows, generic association/relation discovery/mutation helpers, class/interface/mixin, attribute, enum, plugin configuration, domain index configuration, sequence, and space type capability discovery.";
|
|
178725
|
-
var coreGapRationale = "Remaining core write-side configuration, role
|
|
179107
|
+
var coreGapRationale = "Remaining core write-side configuration, role/permission definition writes, generic space creation, class collaborator metadata, statuses, and write-side model management are represented as matrix gaps. Generic space discovery, space type/permission reads, safe existing-space metadata updates, member mutations, owner replacement, typed-space role member mutations, object collaborators, read-only plugin configuration, domain index configuration, and sequence discovery are covered.";
|
|
178726
179108
|
var coreNotMcpFacingRationale = "Core primitive model infrastructure, transaction classes, type wrappers, and versioning internals are not LLM-facing product resources by themselves.";
|
|
178727
179109
|
var routingRow = (classId, packageName, exportName, hint) => ({
|
|
178728
179110
|
classId: ObjectClassName.make(classId),
|
|
@@ -179513,6 +179895,19 @@ var createDirectMessage = (params) => Effect_exports.gen(function* () {
|
|
|
179513
179895
|
return { id: ChannelId.make(dmId), created: true };
|
|
179514
179896
|
});
|
|
179515
179897
|
|
|
179898
|
+
// src/huly/operations/external-channel-messages.ts
|
|
179899
|
+
var EXTERNAL_CHANNEL_PACKAGE_INCOMPATIBLE_REASON = "package-incompatible: package.json and pnpm-lock.yaml include @hcengineering/contact provider refs for email/telegram, but no compatible Huly Gmail or Telegram message SDK package/model is installed; local platform-api examples only expose contact.class.Channel provider values, not external message documents";
|
|
179900
|
+
var listExternalChannelMessages = (params) => Effect_exports.sync(
|
|
179901
|
+
() => encodeListExternalChannelMessagesResult({
|
|
179902
|
+
supported: false,
|
|
179903
|
+
provider: params.provider,
|
|
179904
|
+
channel: params.channel,
|
|
179905
|
+
limit: params.limit ?? DEFAULT_EXTERNAL_CHANNEL_MESSAGE_LIMIT,
|
|
179906
|
+
unsupportedReason: EXTERNAL_CHANNEL_PACKAGE_INCOMPATIBLE_REASON,
|
|
179907
|
+
messages: []
|
|
179908
|
+
})
|
|
179909
|
+
);
|
|
179910
|
+
|
|
179516
179911
|
// src/huly/operations/threads.ts
|
|
179517
179912
|
var import_core31 = __toESM(require_lib4(), 1);
|
|
179518
179913
|
var findReply = (client, channel, message, replyId) => Effect_exports.gen(function* () {
|
|
@@ -179806,6 +180201,17 @@ var channelTools = [
|
|
|
179806
180201
|
listChannelMessages
|
|
179807
180202
|
)
|
|
179808
180203
|
},
|
|
180204
|
+
{
|
|
180205
|
+
name: "list_external_channel_messages",
|
|
180206
|
+
description: "List read-only messages for an external Gmail or Telegram channel by channel name or ID. The limit defaults to 50 and is capped at 200. When this build does not include a compatible Huly external-message SDK/model for the requested provider, returns supported=false, an unsupportedReason, and an empty messages array; it never sends, replies, deletes, mutates, or returns fake messages.",
|
|
180207
|
+
category: CATEGORY6,
|
|
180208
|
+
inputSchema: listExternalChannelMessagesParamsJsonSchema,
|
|
180209
|
+
handler: createToolHandler(
|
|
180210
|
+
"list_external_channel_messages",
|
|
180211
|
+
parseListExternalChannelMessagesParams,
|
|
180212
|
+
listExternalChannelMessages
|
|
180213
|
+
)
|
|
180214
|
+
},
|
|
179809
180215
|
{
|
|
179810
180216
|
name: "send_channel_message",
|
|
179811
180217
|
description: "Send a message to a Huly channel. Message body supports markdown formatting.",
|
|
@@ -186694,6 +187100,18 @@ var labelTools = [
|
|
|
186694
187100
|
// src/huly/operations/leads.ts
|
|
186695
187101
|
var import_core50 = __toESM(require_lib4(), 1);
|
|
186696
187102
|
var funnelAsSpace = (funnel) => toRef(funnel._id);
|
|
187103
|
+
var statusInfosWithFallbacks = (statusRefs, statusDocs) => resolveByStatusRef(
|
|
187104
|
+
statusRefs,
|
|
187105
|
+
statusDocs,
|
|
187106
|
+
(statusDoc) => ({
|
|
187107
|
+
_id: statusDoc._id,
|
|
187108
|
+
name: statusDoc.name
|
|
187109
|
+
}),
|
|
187110
|
+
(statusRef) => ({
|
|
187111
|
+
_id: statusRef,
|
|
187112
|
+
name: workflowStatusFromRef(statusRef).name
|
|
187113
|
+
})
|
|
187114
|
+
);
|
|
186697
187115
|
var markupBlobRefAsMarkupRef = (value3) => value3;
|
|
186698
187116
|
var normalizeLeadIdentifier = (identifier2) => {
|
|
186699
187117
|
const match16 = /^(?:LEAD-)?(\d+)$/i.exec(identifier2.trim());
|
|
@@ -186742,7 +187160,7 @@ var getFunnelStatuses = (client, funnel) => Effect_exports.gen(function* () {
|
|
|
186742
187160
|
})
|
|
186743
187161
|
);
|
|
186744
187162
|
}
|
|
186745
|
-
const statusRefs = projectType.statuses.map((status) => status._id);
|
|
187163
|
+
const statusRefs = uniqueStatusRefs(projectType.statuses.map((status) => status._id));
|
|
186746
187164
|
if (statusRefs.length === 0) {
|
|
186747
187165
|
return yield* Effect_exports.fail(
|
|
186748
187166
|
new HulyConnectionError({
|
|
@@ -186750,14 +187168,8 @@ var getFunnelStatuses = (client, funnel) => Effect_exports.gen(function* () {
|
|
|
186750
187168
|
})
|
|
186751
187169
|
);
|
|
186752
187170
|
}
|
|
186753
|
-
const statusDocs = yield* client
|
|
186754
|
-
|
|
186755
|
-
{ _id: { $in: [...statusRefs] } }
|
|
186756
|
-
);
|
|
186757
|
-
return statusDocs.map((doc) => ({
|
|
186758
|
-
_id: doc._id,
|
|
186759
|
-
name: doc.name
|
|
186760
|
-
}));
|
|
187171
|
+
const statusDocs = yield* findStatusDocs(client, statusRefs);
|
|
187172
|
+
return statusInfosWithFallbacks(statusRefs, statusDocs);
|
|
186761
187173
|
});
|
|
186762
187174
|
var resolveStatusName2 = (statuses, statusId) => {
|
|
186763
187175
|
const statusDoc = statuses.find((status) => status._id === statusId);
|
|
@@ -189553,14 +189965,15 @@ var toSpaceSummary = (space) => ({
|
|
|
189553
189965
|
membersCount: Count.make(space.members.length),
|
|
189554
189966
|
ownersCount: Count.make(space.owners?.length ?? 0)
|
|
189555
189967
|
});
|
|
189556
|
-
var roleAssignments = (space) => {
|
|
189557
|
-
if (
|
|
189558
|
-
|
|
189968
|
+
var roleAssignments = (space, spaceType, validRoleIds) => {
|
|
189969
|
+
if (spaceType === void 0) return void 0;
|
|
189970
|
+
const entries2 = spaceRoleAssignmentEntries(space, spaceType, validRoleIds);
|
|
189971
|
+
return entries2.length === 0 ? void 0 : entries2.map(([roleId, members]) => ({
|
|
189559
189972
|
roleId: RoleId.make(roleId),
|
|
189560
|
-
members:
|
|
189973
|
+
members: members.map((member) => AccountUuid.make(member))
|
|
189561
189974
|
}));
|
|
189562
189975
|
};
|
|
189563
|
-
var toSpaceDetail = (space) => ({
|
|
189976
|
+
var toSpaceDetail = (space, spaceType, validRoleIds = /* @__PURE__ */ new Set()) => ({
|
|
189564
189977
|
id: SpaceId.make(space._id),
|
|
189565
189978
|
name: space.name,
|
|
189566
189979
|
description: space.description,
|
|
@@ -189571,7 +189984,7 @@ var toSpaceDetail = (space) => ({
|
|
|
189571
189984
|
autoJoin: space.autoJoin,
|
|
189572
189985
|
members: space.members.map((member) => AccountUuid.make(member)),
|
|
189573
189986
|
owners: (space.owners ?? []).map((owner) => AccountUuid.make(owner)),
|
|
189574
|
-
roleAssignments: roleAssignments(space)
|
|
189987
|
+
roleAssignments: roleAssignments(space, spaceType, validRoleIds)
|
|
189575
189988
|
});
|
|
189576
189989
|
var spaceTypeSummary = (spaceType, descriptor3) => ({
|
|
189577
189990
|
id: SpaceTypeId.make(spaceType._id),
|
|
@@ -189653,8 +190066,28 @@ var listSpaces = (params) => Effect_exports.gen(function* () {
|
|
|
189653
190066
|
});
|
|
189654
190067
|
var getSpace = (params) => Effect_exports.gen(function* () {
|
|
189655
190068
|
const client = yield* HulyClient;
|
|
190069
|
+
const diagnostics = yield* Diagnostics;
|
|
189656
190070
|
const space = yield* findSpace(client, params);
|
|
189657
|
-
|
|
190071
|
+
const spaceType = space.type === void 0 ? void 0 : yield* client.findOne(
|
|
190072
|
+
core.class.SpaceType,
|
|
190073
|
+
hulyQuery({ _id: toRef(space.type) })
|
|
190074
|
+
);
|
|
190075
|
+
const roles = spaceType === void 0 ? [] : yield* client.findAll(
|
|
190076
|
+
core.class.Role,
|
|
190077
|
+
hulyQuery({ attachedTo: spaceType._id }),
|
|
190078
|
+
{ limit: Math.max(spaceType.roles, 1) }
|
|
190079
|
+
);
|
|
190080
|
+
const validRoleIds = new Set(roles.map((role) => role._id));
|
|
190081
|
+
if (spaceType !== void 0) {
|
|
190082
|
+
const readResult = readSpaceRoleAssignmentEntries(space, spaceType, validRoleIds);
|
|
190083
|
+
if (readResult.degradationReasons.length > 0) {
|
|
190084
|
+
yield* diagnostics.warnAgent({
|
|
190085
|
+
code: SpaceRoleAssignmentsDegradedWarningCode,
|
|
190086
|
+
message: roleAssignmentDegradationMessage(readResult.degradationReasons)
|
|
190087
|
+
});
|
|
190088
|
+
}
|
|
190089
|
+
}
|
|
190090
|
+
return toSpaceDetail(space, spaceType, validRoleIds);
|
|
189658
190091
|
});
|
|
189659
190092
|
var listSpaceTypes = (params) => Effect_exports.gen(function* () {
|
|
189660
190093
|
const client = yield* HulyClient;
|
|
@@ -189837,8 +190270,8 @@ var describeHulySpaceTypeCapabilities = (params) => Effect_exports.gen(function*
|
|
|
189837
190270
|
roles: detail.roles,
|
|
189838
190271
|
rolePermissions: detail.availablePermissions,
|
|
189839
190272
|
assignmentShape: {
|
|
189840
|
-
storedOnSpaceField: HulyConfigurationMetadataKey.make(
|
|
189841
|
-
roleKeyField: HulyConfigurationMetadataKey.make("
|
|
190273
|
+
storedOnSpaceField: HulyConfigurationMetadataKey.make(`mixin:${detail.targetClass}`),
|
|
190274
|
+
roleKeyField: HulyConfigurationMetadataKey.make("role._id"),
|
|
189842
190275
|
memberValueShape: "accountUuidArrayOrUndefined",
|
|
189843
190276
|
readProjectionTools: ["get_space"].map((tool) => HulyMcpToolName.make(tool))
|
|
189844
190277
|
}
|
|
@@ -190172,6 +190605,104 @@ var searchTools = [
|
|
|
190172
190605
|
];
|
|
190173
190606
|
|
|
190174
190607
|
// src/huly/operations/spaces-write.ts
|
|
190608
|
+
var roleClass = core.class.Role;
|
|
190609
|
+
var spaceTypeClass = core.class.SpaceType;
|
|
190610
|
+
var requireTypedSpaceType = (space) => Effect_exports.gen(function* () {
|
|
190611
|
+
if (space.type === void 0) {
|
|
190612
|
+
return yield* new SpaceNotTypedError({
|
|
190613
|
+
id: SpaceId.make(space._id),
|
|
190614
|
+
name: NonEmptyString2.make(space.name)
|
|
190615
|
+
});
|
|
190616
|
+
}
|
|
190617
|
+
return SpaceTypeId.make(space.type);
|
|
190618
|
+
});
|
|
190619
|
+
var findSpaceType2 = (client, spaceType) => Effect_exports.gen(function* () {
|
|
190620
|
+
const result = yield* client.findOne(
|
|
190621
|
+
spaceTypeClass,
|
|
190622
|
+
hulyQuery({ _id: toRef(spaceType) })
|
|
190623
|
+
);
|
|
190624
|
+
if (result === void 0) {
|
|
190625
|
+
return yield* new SpaceRoleNotFoundError({
|
|
190626
|
+
identifier: NonEmptyString2.make("SpaceType roles"),
|
|
190627
|
+
spaceType
|
|
190628
|
+
});
|
|
190629
|
+
}
|
|
190630
|
+
return result;
|
|
190631
|
+
});
|
|
190632
|
+
var resolveSpaceRole = (client, spaceType, role) => Effect_exports.gen(function* () {
|
|
190633
|
+
const byId = yield* client.findOne(
|
|
190634
|
+
roleClass,
|
|
190635
|
+
hulyQuery({
|
|
190636
|
+
_id: toRef(role),
|
|
190637
|
+
attachedTo: toRef(spaceType)
|
|
190638
|
+
})
|
|
190639
|
+
);
|
|
190640
|
+
if (byId !== void 0) return byId;
|
|
190641
|
+
const matches = yield* client.findAll(
|
|
190642
|
+
roleClass,
|
|
190643
|
+
hulyQuery({
|
|
190644
|
+
attachedTo: toRef(spaceType),
|
|
190645
|
+
name: role
|
|
190646
|
+
}),
|
|
190647
|
+
{ limit: 2 }
|
|
190648
|
+
);
|
|
190649
|
+
if (matches.length === 0) {
|
|
190650
|
+
return yield* new SpaceRoleNotFoundError({
|
|
190651
|
+
identifier: NonEmptyString2.make(role),
|
|
190652
|
+
spaceType
|
|
190653
|
+
});
|
|
190654
|
+
}
|
|
190655
|
+
if (matches.length > 1) {
|
|
190656
|
+
return yield* new SpaceRoleIdentifierAmbiguousError({
|
|
190657
|
+
identifier: NonEmptyString2.make(role),
|
|
190658
|
+
spaceType,
|
|
190659
|
+
matches: matches.map((match16) => ({
|
|
190660
|
+
id: RoleId.make(match16._id),
|
|
190661
|
+
name: NonEmptyString2.make(match16.name)
|
|
190662
|
+
}))
|
|
190663
|
+
});
|
|
190664
|
+
}
|
|
190665
|
+
return matches[0];
|
|
190666
|
+
});
|
|
190667
|
+
var findSpaceTypeRoles = (client, spaceType) => client.findAll(
|
|
190668
|
+
roleClass,
|
|
190669
|
+
hulyQuery({ attachedTo: spaceType._id }),
|
|
190670
|
+
{ limit: Math.max(spaceType.roles, 1) }
|
|
190671
|
+
);
|
|
190672
|
+
var writeSpaceRoleMembers = (client, space, spaceType, role, currentAssignments, members) => {
|
|
190673
|
+
const mixin = spaceRoleAssignmentsMixin(spaceType);
|
|
190674
|
+
const attributes = { ...currentAssignments, [role._id]: members };
|
|
190675
|
+
const objectId = toRef(space._id);
|
|
190676
|
+
const objectClass = toClassRef(space._class);
|
|
190677
|
+
const objectSpace = toRef(space.space);
|
|
190678
|
+
return hasSpaceRoleAssignmentMixin(space, spaceType) ? client.updateMixin(objectId, objectClass, objectSpace, mixin, attributes).pipe(Effect_exports.asVoid) : client.createMixin(objectId, objectClass, objectSpace, mixin, attributes).pipe(Effect_exports.asVoid);
|
|
190679
|
+
};
|
|
190680
|
+
var mutateSpaceRoleMembers = (params, mutateMembers) => Effect_exports.gen(function* () {
|
|
190681
|
+
const client = yield* HulyClient;
|
|
190682
|
+
const space = yield* findSpace(client, params);
|
|
190683
|
+
const spaceType = yield* requireTypedSpaceType(space);
|
|
190684
|
+
const spaceTypeDoc = yield* findSpaceType2(client, spaceType);
|
|
190685
|
+
const role = yield* resolveSpaceRole(client, spaceType, params.role);
|
|
190686
|
+
const validRoles = yield* findSpaceTypeRoles(client, spaceTypeDoc);
|
|
190687
|
+
const resolvedMembers = yield* resolveMembers(client, params.members);
|
|
190688
|
+
const currentAssignments = yield* strictSpaceRoleAssignments(
|
|
190689
|
+
space,
|
|
190690
|
+
spaceTypeDoc,
|
|
190691
|
+
new Set(validRoles.map((validRole) => validRole._id))
|
|
190692
|
+
);
|
|
190693
|
+
const currentMembers = sortStrings(currentAssignments[role._id] ?? []).map(toAccountUuid);
|
|
190694
|
+
const nextMembers = mutateMembers(currentMembers, resolvedMembers).map(toAccountUuid);
|
|
190695
|
+
const changed = !arraysEqual(currentMembers, nextMembers);
|
|
190696
|
+
if (changed) {
|
|
190697
|
+
yield* writeSpaceRoleMembers(client, space, spaceTypeDoc, role, currentAssignments, nextMembers);
|
|
190698
|
+
}
|
|
190699
|
+
return {
|
|
190700
|
+
id: SpaceId.make(space._id),
|
|
190701
|
+
roleId: RoleId.make(role._id),
|
|
190702
|
+
members: nextMembers.map((member) => AccountUuid.make(member)),
|
|
190703
|
+
changed
|
|
190704
|
+
};
|
|
190705
|
+
});
|
|
190175
190706
|
var mutateSpaceMembers = (params, mutateMembers) => Effect_exports.gen(function* () {
|
|
190176
190707
|
const client = yield* HulyClient;
|
|
190177
190708
|
const space = yield* findSpace(client, params);
|
|
@@ -190224,6 +190755,9 @@ var setSpaceOwners = (params) => Effect_exports.gen(function* () {
|
|
|
190224
190755
|
changed: changedOwners || changedMembers
|
|
190225
190756
|
};
|
|
190226
190757
|
});
|
|
190758
|
+
var setSpaceRoleMembers = (params) => mutateSpaceRoleMembers(params, (_currentMembers, resolvedMembers) => sortStrings(resolvedMembers).map(toAccountUuid));
|
|
190759
|
+
var addSpaceRoleMembers = (params) => mutateSpaceRoleMembers(params, mergeUniqueSortedAccountUuids);
|
|
190760
|
+
var removeSpaceRoleMembers = (params) => mutateSpaceRoleMembers(params, removeAccountUuids);
|
|
190227
190761
|
|
|
190228
190762
|
// src/mcp/tools/spaces.ts
|
|
190229
190763
|
var CATEGORY28 = "spaces";
|
|
@@ -190290,6 +190824,30 @@ var spaceTools = [
|
|
|
190290
190824
|
category: CATEGORY28,
|
|
190291
190825
|
inputSchema: setSpaceOwnersParamsJsonSchema,
|
|
190292
190826
|
handler: createToolHandler("set_space_owners", parseSetSpaceOwnersParams, setSpaceOwners)
|
|
190827
|
+
},
|
|
190828
|
+
{
|
|
190829
|
+
name: "set_space_role_members",
|
|
190830
|
+
description: "Replace members assigned to one role on a typed Huly space while preserving all other role assignments. Role accepts a raw role _id or exact role name from the space's SpaceType. Members accept account UUID, exact email, or exact person display name; pass members=[] to clear this role.",
|
|
190831
|
+
category: CATEGORY28,
|
|
190832
|
+
inputSchema: setSpaceRoleMembersParamsJsonSchema,
|
|
190833
|
+
annotations: { idempotentHint: true, destructiveHint: false },
|
|
190834
|
+
handler: createToolHandler("set_space_role_members", parseSetSpaceRoleMembersParams, setSpaceRoleMembers)
|
|
190835
|
+
},
|
|
190836
|
+
{
|
|
190837
|
+
name: "add_space_role_members",
|
|
190838
|
+
description: "Idempotently add members to one role on a typed Huly space while preserving all other role assignments. Role accepts a raw role _id or exact role name from the space's SpaceType. Members accept account UUID, exact email, or exact person display name.",
|
|
190839
|
+
category: CATEGORY28,
|
|
190840
|
+
inputSchema: spaceRoleMemberMutationParamsJsonSchema,
|
|
190841
|
+
annotations: { idempotentHint: true, destructiveHint: false },
|
|
190842
|
+
handler: createToolHandler("add_space_role_members", parseSpaceRoleMemberMutationParams, addSpaceRoleMembers)
|
|
190843
|
+
},
|
|
190844
|
+
{
|
|
190845
|
+
name: "remove_space_role_members",
|
|
190846
|
+
description: "Idempotently remove members from one role on a typed Huly space while preserving all other role assignments. Role accepts a raw role _id or exact role name from the space's SpaceType. Members accept account UUID, exact email, or exact person display name.",
|
|
190847
|
+
category: CATEGORY28,
|
|
190848
|
+
inputSchema: spaceRoleMemberMutationParamsJsonSchema,
|
|
190849
|
+
annotations: { idempotentHint: true, destructiveHint: false },
|
|
190850
|
+
handler: createToolHandler("remove_space_role_members", parseSpaceRoleMemberMutationParams, removeSpaceRoleMembers)
|
|
190293
190851
|
}
|
|
190294
190852
|
];
|
|
190295
190853
|
|
|
@@ -190591,7 +191149,7 @@ var STATUS_CATEGORIES = Object.values(STATUS_CATEGORY_BY_SDK_KEY).map((entry) =>
|
|
|
190591
191149
|
name: entry.name
|
|
190592
191150
|
}));
|
|
190593
191151
|
var WORKFLOW_WARNING = "This changes workspace-level tracker configuration for every project using this project type.";
|
|
190594
|
-
var toCategoryValue = (category) => category === void 0 ?
|
|
191152
|
+
var toCategoryValue = (category) => category === void 0 ? UnknownStatusCategoryValue : REF_TO_CATEGORY.get(category) ?? UnknownStatusCategoryValue;
|
|
190595
191153
|
var encodeOrConnectionError2 = (schema, value3, operation) => Schema_exports.encode(schema)(value3).pipe(
|
|
190596
191154
|
Effect_exports.as(value3),
|
|
190597
191155
|
Effect_exports.mapError(
|
|
@@ -190607,9 +191165,17 @@ var uniqueProjectStatuses = (statuses) => statuses.reduce(
|
|
|
190607
191165
|
(unique, status) => unique.some((existing) => sameProjectStatus(existing, status)) ? unique : [...unique, status],
|
|
190608
191166
|
[]
|
|
190609
191167
|
);
|
|
190610
|
-
var getStatusDocs = (client, statusIds) => statusIds.length === 0 ? Effect_exports.succeed([]) : client
|
|
190611
|
-
|
|
190612
|
-
|
|
191168
|
+
var getStatusDocs = (client, statusIds) => statusIds.length === 0 ? Effect_exports.succeed([]) : findStatusDocs(client, statusIds);
|
|
191169
|
+
var fallbackStatusDoc = (statusId) => ({
|
|
191170
|
+
_id: statusId,
|
|
191171
|
+
_class: core.class.Status,
|
|
191172
|
+
space: core.space.Model,
|
|
191173
|
+
modifiedOn: 0,
|
|
191174
|
+
modifiedBy: core.account.System,
|
|
191175
|
+
ofAttribute: tracker.attribute.IssueStatus,
|
|
191176
|
+
name: workflowStatusFromRef(statusId).name
|
|
191177
|
+
});
|
|
191178
|
+
var statusDocsWithFallbacks = (statusIds, statusDocs) => resolveByStatusRef(statusIds, statusDocs, (statusDoc) => statusDoc, fallbackStatusDoc);
|
|
190613
191179
|
var getTaskTypes = (client, taskTypeIds) => taskTypeIds.length === 0 ? Effect_exports.succeed([]) : client.findAll(task.class.TaskType, hulyQuery({ _id: { $in: [...taskTypeIds] } })).pipe(
|
|
190614
191180
|
Effect_exports.map((result) => [...result])
|
|
190615
191181
|
);
|
|
@@ -190628,7 +191194,9 @@ var getRecoverableStatusesByName = (client, name) => client.findAll(core.class.S
|
|
|
190628
191194
|
);
|
|
190629
191195
|
var loadWorkflowData = (client, projectType) => Effect_exports.gen(function* () {
|
|
190630
191196
|
const taskTypes = yield* getTaskTypes(client, projectType.tasks);
|
|
190631
|
-
const
|
|
191197
|
+
const statusIds = uniqueStatusIds(projectType);
|
|
191198
|
+
const statusDocs = yield* getStatusDocs(client, statusIds);
|
|
191199
|
+
const statuses = statusDocsWithFallbacks(statusIds, statusDocs);
|
|
190632
191200
|
return { projectType, taskTypes, statuses };
|
|
190633
191201
|
});
|
|
190634
191202
|
var isDefaultClassicProjectType = (projectType) => projectType._id === tracker.ids.ClassingProjectType || projectType.classic || normalizeForComparison(projectType.name) === "classic";
|
|
@@ -193351,6 +193919,13 @@ var DRAIN_TIMEOUT_MS2 = 3e4;
|
|
|
193351
193919
|
var NPM_FETCH_TIMEOUT_MS = 5e3;
|
|
193352
193920
|
var NPM_PACKAGE_NAME2 = "@firfi/huly-mcp";
|
|
193353
193921
|
var computeOutputBytes = (response) => response.content.reduce((sum2, c) => sum2 + c.text.length, 0);
|
|
193922
|
+
var withResourceWarnings = (result, warnings) => warnings.length === 0 ? result : {
|
|
193923
|
+
...result,
|
|
193924
|
+
_meta: {
|
|
193925
|
+
...result._meta,
|
|
193926
|
+
warnings
|
|
193927
|
+
}
|
|
193928
|
+
};
|
|
193354
193929
|
var deriveEditMode = (name, args2) => {
|
|
193355
193930
|
if (name !== "edit_document" || args2 === void 0) return void 0;
|
|
193356
193931
|
if (typeof args2 !== "object" || args2 === null || Array.isArray(args2)) return void 0;
|
|
@@ -193587,12 +194162,15 @@ var createMcpProtocolHandlers = (resolveClients, telemetry, registry2, getHulyCo
|
|
|
193587
194162
|
resolveClients,
|
|
193588
194163
|
(error2) => createResourceClientResolutionError(uri, error2)
|
|
193589
194164
|
);
|
|
194165
|
+
const diagnosticsScope = await Effect_exports.runPromise(makeDiagnosticsScope);
|
|
193590
194166
|
const resourceRead = await Effect_exports.runPromiseExit(
|
|
193591
194167
|
readHulyResource(uri).pipe(
|
|
193592
|
-
Effect_exports.provideService(HulyClient, clients.hulyClient)
|
|
194168
|
+
Effect_exports.provideService(HulyClient, clients.hulyClient),
|
|
194169
|
+
Effect_exports.provideService(Diagnostics, diagnosticsScope.service)
|
|
193593
194170
|
)
|
|
193594
194171
|
);
|
|
193595
|
-
|
|
194172
|
+
const warnings = await Effect_exports.runPromise(diagnosticsScope.drainWarnings);
|
|
194173
|
+
if (Exit_exports.isSuccess(resourceRead)) return withResourceWarnings(resourceRead.value, warnings);
|
|
193596
194174
|
return throwResourceReadError(uri, resourceRead.cause);
|
|
193597
194175
|
} finally {
|
|
193598
194176
|
leave();
|