huly-mcp-selfhost 2.1.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +39 -2
- package/README.md +462 -16
- package/dist/connection.d.ts +8 -0
- package/dist/connection.js +13 -1
- package/dist/connection.js.map +1 -1
- package/dist/env.d.ts +1 -0
- package/dist/env.js +17 -0
- package/dist/env.js.map +1 -0
- package/dist/guard.d.ts +28 -0
- package/dist/guard.js +152 -0
- package/dist/guard.js.map +1 -0
- package/dist/guides/costs.md +48 -0
- package/dist/guides/features.md +49 -0
- package/dist/guides/onboarding.md +56 -0
- package/dist/guides/workflow.md +57 -0
- package/dist/index.js +18 -1
- package/dist/index.js.map +1 -1
- package/dist/junit-cli.d.ts +8 -0
- package/dist/junit-cli.js +106 -0
- package/dist/junit-cli.js.map +1 -0
- package/dist/registry.d.ts +18 -0
- package/dist/registry.js +318 -0
- package/dist/registry.js.map +1 -0
- package/dist/resources.d.ts +12 -0
- package/dist/resources.js +212 -0
- package/dist/resources.js.map +1 -0
- package/dist/schemas.d.ts +1269 -17
- package/dist/schemas.js +890 -97
- package/dist/schemas.js.map +1 -1
- package/dist/server.d.ts +27 -1
- package/dist/server.js +197 -128
- package/dist/server.js.map +1 -1
- package/dist/tools/activity.d.ts +10 -0
- package/dist/tools/activity.js +62 -0
- package/dist/tools/activity.js.map +1 -0
- package/dist/tools/agent.d.ts +156 -0
- package/dist/tools/agent.js +523 -0
- package/dist/tools/agent.js.map +1 -0
- package/dist/tools/attachments.d.ts +4 -4
- package/dist/tools/calendar.d.ts +49 -0
- package/dist/tools/calendar.js +116 -0
- package/dist/tools/calendar.js.map +1 -0
- package/dist/tools/cards.d.ts +87 -0
- package/dist/tools/cards.js +246 -0
- package/dist/tools/cards.js.map +1 -0
- package/dist/tools/channels.d.ts +76 -7
- package/dist/tools/channels.js +86 -5
- package/dist/tools/channels.js.map +1 -1
- package/dist/tools/comments.d.ts +16 -4
- package/dist/tools/comments.js +26 -9
- package/dist/tools/comments.js.map +1 -1
- package/dist/tools/components.d.ts +5 -5
- package/dist/tools/components.js +4 -22
- package/dist/tools/components.js.map +1 -1
- package/dist/tools/contacts.d.ts +69 -0
- package/dist/tools/contacts.js +130 -0
- package/dist/tools/contacts.js.map +1 -0
- package/dist/tools/crm.d.ts +61 -0
- package/dist/tools/crm.js +117 -0
- package/dist/tools/crm.js.map +1 -0
- package/dist/tools/documents.d.ts +35 -12
- package/dist/tools/documents.js +107 -22
- package/dist/tools/documents.js.map +1 -1
- package/dist/tools/drive.d.ts +107 -0
- package/dist/tools/drive.js +277 -0
- package/dist/tools/drive.js.map +1 -0
- package/dist/tools/fields.d.ts +33 -0
- package/dist/tools/fields.js +124 -0
- package/dist/tools/fields.js.map +1 -0
- package/dist/tools/generic.d.ts +72 -0
- package/dist/tools/generic.js +242 -0
- package/dist/tools/generic.js.map +1 -0
- package/dist/tools/github.d.ts +21 -0
- package/dist/tools/github.js +80 -0
- package/dist/tools/github.js.map +1 -0
- package/dist/tools/hr.d.ts +97 -0
- package/dist/tools/hr.js +150 -0
- package/dist/tools/hr.js.map +1 -0
- package/dist/tools/inbox.d.ts +23 -0
- package/dist/tools/inbox.js +76 -0
- package/dist/tools/inbox.js.map +1 -0
- package/dist/tools/inventory.d.ts +61 -0
- package/dist/tools/inventory.js +103 -0
- package/dist/tools/inventory.js.map +1 -0
- package/dist/tools/issues.d.ts +63 -12
- package/dist/tools/issues.js +259 -48
- package/dist/tools/issues.js.map +1 -1
- package/dist/tools/labels.d.ts +52 -4
- package/dist/tools/labels.js +86 -4
- package/dist/tools/labels.js.map +1 -1
- package/dist/tools/log-time.d.ts +15 -1
- package/dist/tools/log-time.js +70 -6
- package/dist/tools/log-time.js.map +1 -1
- package/dist/tools/meetings.d.ts +30 -0
- package/dist/tools/meetings.js +78 -0
- package/dist/tools/meetings.js.map +1 -0
- package/dist/tools/members.d.ts +1 -1
- package/dist/tools/members.js +17 -1
- package/dist/tools/members.js.map +1 -1
- package/dist/tools/message-templates.d.ts +54 -0
- package/dist/tools/message-templates.js +88 -0
- package/dist/tools/message-templates.js.map +1 -0
- package/dist/tools/milestones.d.ts +9 -9
- package/dist/tools/organizations.d.ts +5 -5
- package/dist/tools/organizations.js +2 -1
- package/dist/tools/organizations.js.map +1 -1
- package/dist/tools/overview.d.ts +55 -0
- package/dist/tools/overview.js +395 -0
- package/dist/tools/overview.js.map +1 -0
- package/dist/tools/planner.d.ts +60 -0
- package/dist/tools/planner.js +145 -0
- package/dist/tools/planner.js.map +1 -0
- package/dist/tools/process.d.ts +50 -0
- package/dist/tools/process.js +137 -0
- package/dist/tools/process.js.map +1 -0
- package/dist/tools/products.d.ts +17 -0
- package/dist/tools/products.js +45 -0
- package/dist/tools/products.js.map +1 -0
- package/dist/tools/projects.d.ts +17 -4
- package/dist/tools/projects.js +31 -2
- package/dist/tools/projects.js.map +1 -1
- package/dist/tools/qms.d.ts +57 -0
- package/dist/tools/qms.js +171 -0
- package/dist/tools/qms.js.map +1 -0
- package/dist/tools/recruiting.d.ts +112 -0
- package/dist/tools/recruiting.js +203 -0
- package/dist/tools/recruiting.js.map +1 -0
- package/dist/tools/relations.d.ts +45 -3
- package/dist/tools/relations.js +128 -39
- package/dist/tools/relations.js.map +1 -1
- package/dist/tools/search.d.ts +14 -1
- package/dist/tools/search.js +29 -1
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/sharing.d.ts +62 -0
- package/dist/tools/sharing.js +149 -0
- package/dist/tools/sharing.js.map +1 -0
- package/dist/tools/statuses.d.ts +3 -3
- package/dist/tools/surveys.d.ts +22 -0
- package/dist/tools/surveys.js +53 -0
- package/dist/tools/surveys.js.map +1 -0
- package/dist/tools/templates.d.ts +95 -0
- package/dist/tools/templates.js +260 -0
- package/dist/tools/templates.js.map +1 -0
- package/dist/tools/test-automation.d.ts +81 -0
- package/dist/tools/test-automation.js +225 -0
- package/dist/tools/test-automation.js.map +1 -0
- package/dist/tools/testing.d.ts +234 -0
- package/dist/tools/testing.js +401 -0
- package/dist/tools/testing.js.map +1 -0
- package/dist/tools/workspace-admin.d.ts +55 -0
- package/dist/tools/workspace-admin.js +117 -0
- package/dist/tools/workspace-admin.js.map +1 -0
- package/dist/tools/workspaces.d.ts +1 -1
- package/dist/utils/attributes.d.ts +37 -0
- package/dist/utils/attributes.js +188 -0
- package/dist/utils/attributes.js.map +1 -0
- package/dist/utils/classes.d.ts +51 -0
- package/dist/utils/classes.js +73 -0
- package/dist/utils/classes.js.map +1 -0
- package/dist/utils/content.d.ts +11 -0
- package/dist/utils/content.js +86 -0
- package/dist/utils/content.js.map +1 -0
- package/dist/utils/errors.js +1 -1
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/files.d.ts +5 -0
- package/dist/utils/files.js +50 -0
- package/dist/utils/files.js.map +1 -0
- package/dist/utils/format.d.ts +2 -0
- package/dist/utils/format.js +7 -13
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/junit.d.ts +13 -0
- package/dist/utils/junit.js +81 -0
- package/dist/utils/junit.js.map +1 -0
- package/dist/utils/markdown.js +9 -4
- package/dist/utils/markdown.js.map +1 -1
- package/dist/utils/meeting.d.ts +13 -0
- package/dist/utils/meeting.js +118 -0
- package/dist/utils/meeting.js.map +1 -0
- package/dist/utils/people.d.ts +25 -0
- package/dist/utils/people.js +80 -0
- package/dist/utils/people.js.map +1 -0
- package/dist/utils/redact.d.ts +3 -0
- package/dist/utils/redact.js +26 -0
- package/dist/utils/redact.js.map +1 -0
- package/dist/utils/resolve.d.ts +17 -0
- package/dist/utils/resolve.js +54 -0
- package/dist/utils/resolve.js.map +1 -0
- package/dist/utils/spec.d.ts +10 -0
- package/dist/utils/spec.js +90 -0
- package/dist/utils/spec.js.map +1 -0
- package/dist/utils/storage.js +7 -3
- package/dist/utils/storage.js.map +1 -1
- package/dist/utils/tasks.d.ts +22 -0
- package/dist/utils/tasks.js +81 -0
- package/dist/utils/tasks.js.map +1 -0
- package/dist/watch.d.ts +62 -0
- package/dist/watch.js +405 -0
- package/dist/watch.js.map +1 -0
- package/package.json +4 -3
- package/scripts/setup.js +3 -1
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// People in Huly 0.7: every user is a contact.class.Person with the contact.mixin.Employee
|
|
3
|
+
// mixin (contact.class.Member is the membership of a person in an organization — it is
|
|
4
|
+
// empty for most workspaces and must not be used to find users). Names are stored as
|
|
5
|
+
// "Last,First". Changes are attributed to a PersonId (social identity), which
|
|
6
|
+
// contact.class.SocialIdentity maps back to its Person.
|
|
7
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
8
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9
|
+
};
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.formatPersonName = formatPersonName;
|
|
12
|
+
exports.listPeople = listPeople;
|
|
13
|
+
exports.peopleNames = peopleNames;
|
|
14
|
+
exports.findPerson = findPerson;
|
|
15
|
+
exports.currentPerson = currentPerson;
|
|
16
|
+
exports.socialIdNames = socialIdNames;
|
|
17
|
+
exports.currentAccountUuid = currentAccountUuid;
|
|
18
|
+
const contact_1 = __importDefault(require("@hcengineering/contact"));
|
|
19
|
+
/** "Conrad,Joris" → "Joris Conrad"; other formats are returned trimmed. */
|
|
20
|
+
function formatPersonName(raw) {
|
|
21
|
+
if (raw == null)
|
|
22
|
+
return '';
|
|
23
|
+
const [last, first] = raw.split(',', 2);
|
|
24
|
+
if (first === undefined)
|
|
25
|
+
return raw.trim();
|
|
26
|
+
return `${first.trim()} ${last.trim()}`.trim();
|
|
27
|
+
}
|
|
28
|
+
/** Workspace users (employees); falls back to all persons if the mixin query returns nothing. */
|
|
29
|
+
async function listPeople(client) {
|
|
30
|
+
let docs = await client.findAll(contact_1.default.mixin.Employee, {});
|
|
31
|
+
if (docs.length === 0)
|
|
32
|
+
docs = await client.findAll(contact_1.default.class.Person, {});
|
|
33
|
+
return docs.map((d) => ({ _id: d._id, rawName: d.name ?? '', name: formatPersonName(d.name) }));
|
|
34
|
+
}
|
|
35
|
+
/** Map person id → display name. */
|
|
36
|
+
async function peopleNames(client) {
|
|
37
|
+
return new Map((await listPeople(client)).map((p) => [p._id, p.name]));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Finds one user by name ("Joris", "Conrad", "Joris Conrad", "Conrad,Joris"), case-insensitive.
|
|
41
|
+
* An exact full-name match wins; otherwise the query must match exactly one person.
|
|
42
|
+
*/
|
|
43
|
+
async function findPerson(client, query) {
|
|
44
|
+
const q = query.trim().toLowerCase();
|
|
45
|
+
const people = await listPeople(client);
|
|
46
|
+
const exact = people.filter((p) => p.name.toLowerCase() === q || p.rawName.toLowerCase() === q);
|
|
47
|
+
if (exact.length === 1)
|
|
48
|
+
return exact[0];
|
|
49
|
+
const partial = people.filter((p) => p.name.toLowerCase().includes(q) || p.rawName.toLowerCase().includes(q));
|
|
50
|
+
if (partial.length === 1)
|
|
51
|
+
return partial[0];
|
|
52
|
+
if (partial.length === 0)
|
|
53
|
+
throw new Error(`Member '${query}' not found.`);
|
|
54
|
+
throw new Error(`Member '${query}' is ambiguous: ${partial.map((p) => p.name).join(', ')}.`);
|
|
55
|
+
}
|
|
56
|
+
/** The Person behind the connected account (via its social identity). */
|
|
57
|
+
async function currentPerson(client) {
|
|
58
|
+
const identity = await client.findOne(contact_1.default.class.SocialIdentity, { _id: client.user });
|
|
59
|
+
const personId = identity?.attachedTo;
|
|
60
|
+
if (personId == null)
|
|
61
|
+
throw new Error('Could not identify current user.');
|
|
62
|
+
const person = await client.findOne(contact_1.default.class.Person, { _id: personId });
|
|
63
|
+
return { _id: personId, rawName: person?.name ?? '', name: formatPersonName(person?.name), uuid: person?.personUuid };
|
|
64
|
+
}
|
|
65
|
+
/** Map social identity (PersonId, e.g. createdBy/modifiedBy) → display name. */
|
|
66
|
+
async function socialIdNames(client, ids) {
|
|
67
|
+
if (ids.length === 0)
|
|
68
|
+
return new Map();
|
|
69
|
+
const identities = await client.findAll(contact_1.default.class.SocialIdentity, { _id: { $in: ids } });
|
|
70
|
+
const names = await peopleNames(client);
|
|
71
|
+
return new Map(identities.map((i) => [i._id, names.get(i.attachedTo) ?? 'Unknown']));
|
|
72
|
+
}
|
|
73
|
+
/** Account UUID of the connected user (inbox notifications and calendars are keyed by it). */
|
|
74
|
+
async function currentAccountUuid(client) {
|
|
75
|
+
const me = await currentPerson(client);
|
|
76
|
+
if (me.uuid == null)
|
|
77
|
+
throw new Error('Could not determine the account of the current user.');
|
|
78
|
+
return me.uuid;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=people.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"people.js","sourceRoot":"","sources":["../../src/utils/people.ts"],"names":[],"mappings":";AAAA,2FAA2F;AAC3F,uFAAuF;AACvF,qFAAqF;AACrF,8EAA8E;AAC9E,wDAAwD;;;;;;;;;;;;AAExD,qEAA4C;AAM5C,2EAA2E;AAC3E,0BAAkC,GAA8B;IAC9D,IAAI,GAAG,IAAI,IAAI;QAAE,OAAO,EAAE,CAAA;IAC1B,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;IACvC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC,IAAI,EAAE,CAAA;IAC1C,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAA;AAChD,CAAC;AAED,iGAAiG;AAC1F,KAAK,qBAAsB,MAAoB;IACpD,IAAI,IAAI,GAAU,MAAM,MAAM,CAAC,OAAO,CAAC,iBAAO,CAAC,KAAK,CAAC,QAAe,EAAE,EAAE,CAAC,CAAA;IACzE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,iBAAO,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IAC5E,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;AACjG,CAAC;AAED,oCAAoC;AAC7B,KAAK,sBAAuB,MAAoB;IACrD,OAAO,IAAI,GAAG,CAAC,CAAC,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAa,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AAClF,CAAC;AAED;;;GAGG;AACI,KAAK,qBAAsB,MAAoB,EAAE,KAAa;IACnE,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IACpC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,CAAA;IACvC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAA;IAC/F,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAA;IACvC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IAC7G,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC,CAAC,CAAC,CAAA;IAC3C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,WAAW,KAAK,cAAc,CAAC,CAAA;IACzE,MAAM,IAAI,KAAK,CAAC,WAAW,KAAK,mBAAmB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAC9F,CAAC;AAED,yEAAyE;AAClE,KAAK,wBAAyB,MAAoB;IACvD,MAAM,QAAQ,GAAQ,MAAM,MAAM,CAAC,OAAO,CAAC,iBAAO,CAAC,KAAK,CAAC,cAAqB,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,IAAW,EAAE,CAAC,CAAA;IAC5G,MAAM,QAAQ,GAAG,QAAQ,EAAE,UAAU,CAAA;IACrC,IAAI,QAAQ,IAAI,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAA;IACzE,MAAM,MAAM,GAAQ,MAAM,MAAM,CAAC,OAAO,CAAC,iBAAO,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAA;IACjF,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAA;AACvH,CAAC;AAED,gFAAgF;AACzE,KAAK,wBAAyB,MAAoB,EAAE,GAAa;IACtE,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,GAAG,EAAE,CAAA;IACtC,MAAM,UAAU,GAAU,MAAM,MAAM,CAAC,OAAO,CAAC,iBAAO,CAAC,KAAK,CAAC,cAAqB,EAAE,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,EAAS,CAAC,CAAA;IACjH,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,CAAA;IACvC,OAAO,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAa,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAA;AAChG,CAAC;AAED,8FAA8F;AACvF,KAAK,6BAA8B,MAAoB;IAC5D,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,CAAA;IACtC,IAAI,EAAE,CAAC,IAAI,IAAI,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAA;IAC5F,OAAO,EAAE,CAAC,IAAI,CAAA;AAChB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.redactSecrets = redactSecrets;
|
|
4
|
+
exports.routeConsoleToStderr = routeConsoleToStderr;
|
|
5
|
+
/**
|
|
6
|
+
* Huly's client logs its websocket URL on errors ("client websocket error: 2 wss://host/_transactor/<JWT> …").
|
|
7
|
+
* The JWT is a valid workspace session token, so it must not end up in container logs.
|
|
8
|
+
*/
|
|
9
|
+
const JWT = /eyJ[\w-]{5,}\.[\w-]{5,}\.[\w-]{5,}/g;
|
|
10
|
+
function redactSecrets(value) {
|
|
11
|
+
if (typeof value === 'string')
|
|
12
|
+
return value.replace(JWT, '***');
|
|
13
|
+
if (value instanceof Error) {
|
|
14
|
+
const copy = new Error(redactSecrets(value.message));
|
|
15
|
+
copy.stack = value.stack != null ? redactSecrets(value.stack) : undefined;
|
|
16
|
+
return copy;
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
/** Server mode: stdout is the JSON-RPC channel, so all console output goes to stderr, with tokens masked. */
|
|
21
|
+
function routeConsoleToStderr() {
|
|
22
|
+
const write = console.error.bind(console);
|
|
23
|
+
const log = (...args) => { write(...args.map(redactSecrets)); };
|
|
24
|
+
console.log = console.info = console.debug = console.warn = console.error = log;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=redact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/utils/redact.ts"],"names":[],"mappings":";;;;AAAA;;;GAGG;AACH,MAAM,GAAG,GAAG,qCAAqC,CAAA;AAEjD,uBAA+B,KAAc;IAC3C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IAC/D,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAW,CAAC,CAAA;QAC9D,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAW,CAAC,CAAC,CAAC,SAAS,CAAA;QACnF,OAAO,IAAI,CAAA;IACb,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,6GAA6G;AAC7G;IACE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACzC,MAAM,GAAG,GAAG,CAAC,GAAG,IAAe,EAAQ,EAAE,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAA,CAAC,CAAC,CAAA;IAC/E,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,KAAK,GAAG,GAAG,CAAA;AACjF,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { TxOperations } from '@hcengineering/core';
|
|
2
|
+
export interface ObjectRef {
|
|
3
|
+
_id: string;
|
|
4
|
+
_class: string;
|
|
5
|
+
space: string;
|
|
6
|
+
label: string;
|
|
7
|
+
doc: any;
|
|
8
|
+
}
|
|
9
|
+
/** Human-readable label for any Huly document: "PROJ-12: title", a title, a name, or message text. */
|
|
10
|
+
export declare function labelOf(doc: any): string;
|
|
11
|
+
/** Loads a document of a known class and labels it; undefined if it no longer exists. */
|
|
12
|
+
export declare function loadLabel(client: TxOperations, _class: string, _id: string): Promise<string>;
|
|
13
|
+
/**
|
|
14
|
+
* Resolves "PROJ-12" (issue, pull request or any task) or a raw document id.
|
|
15
|
+
* For raw ids the class is unknown, so the activity/notification records that point at it are used.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveObject(client: TxOperations, ref: string): Promise<ObjectRef>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.labelOf = labelOf;
|
|
7
|
+
exports.loadLabel = loadLabel;
|
|
8
|
+
exports.resolveObject = resolveObject;
|
|
9
|
+
const task_1 = __importDefault(require("@hcengineering/task"));
|
|
10
|
+
const format_1 = require("./format");
|
|
11
|
+
const TASK_ID = /^[A-Z][A-Z0-9]*-\d+$/;
|
|
12
|
+
/** Human-readable label for any Huly document: "PROJ-12: title", a title, a name, or message text. */
|
|
13
|
+
function labelOf(doc) {
|
|
14
|
+
if (doc == null)
|
|
15
|
+
return '(deleted)';
|
|
16
|
+
const title = doc.title ?? doc.name ?? doc.label;
|
|
17
|
+
if (doc.identifier != null && title != null)
|
|
18
|
+
return `${doc.identifier}: ${title}`;
|
|
19
|
+
if (title != null && title !== '')
|
|
20
|
+
return String(title);
|
|
21
|
+
if (typeof doc.message === 'string')
|
|
22
|
+
return (0, format_1.markupToText)(doc.message).slice(0, 80);
|
|
23
|
+
return String(doc._id);
|
|
24
|
+
}
|
|
25
|
+
/** Loads a document of a known class and labels it; undefined if it no longer exists. */
|
|
26
|
+
async function loadLabel(client, _class, _id) {
|
|
27
|
+
try {
|
|
28
|
+
const doc = await client.findOne(_class, { _id });
|
|
29
|
+
return labelOf(doc);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return String(_id);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Resolves "PROJ-12" (issue, pull request or any task) or a raw document id.
|
|
37
|
+
* For raw ids the class is unknown, so the activity/notification records that point at it are used.
|
|
38
|
+
*/
|
|
39
|
+
async function resolveObject(client, ref) {
|
|
40
|
+
if (TASK_ID.test(ref)) {
|
|
41
|
+
const doc = await client.findOne(task_1.default.class.Task, { identifier: ref });
|
|
42
|
+
if (doc == null)
|
|
43
|
+
throw new Error(`'${ref}' not found.`);
|
|
44
|
+
return { _id: doc._id, _class: doc._class, space: doc.space, label: labelOf(doc), doc };
|
|
45
|
+
}
|
|
46
|
+
const ctx = await client.findOne('notification:class:DocNotifyContext', { objectId: ref });
|
|
47
|
+
const msg = ctx == null ? await client.findOne('activity:class:ActivityMessage', { attachedTo: ref }) : undefined;
|
|
48
|
+
const _class = ctx?.objectClass ?? msg?.attachedToClass;
|
|
49
|
+
if (_class == null)
|
|
50
|
+
throw new Error(`Object '${ref}' not found (pass an issue id like PROJ-12 or an id from another tool).`);
|
|
51
|
+
const doc = await client.findOne(_class, { _id: ref });
|
|
52
|
+
return { _id: ref, _class, space: doc?.space ?? ctx?.objectSpace, label: labelOf(doc), doc };
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/utils/resolve.ts"],"names":[],"mappings":";;;;;;;;AAAA,+DAAsC;AAEtC,qCAAuC;AAIvC,MAAM,OAAO,GAAG,sBAAsB,CAAA;AAEtC,sGAAsG;AACtG,iBAAyB,GAAQ;IAC/B,IAAI,GAAG,IAAI,IAAI;QAAE,OAAO,WAAW,CAAA;IACnC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,KAAK,CAAA;IAChD,IAAI,GAAG,CAAC,UAAU,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,GAAG,GAAG,CAAC,UAAoB,KAAK,KAAe,EAAE,CAAA;IACrG,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAA;IACvD,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;QAAE,OAAO,IAAA,qBAAY,EAAC,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAClF,OAAO,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;AACxB,CAAC;AAED,yFAAyF;AAClF,KAAK,oBAAqB,MAAoB,EAAE,MAAc,EAAE,GAAW;IAChF,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAa,EAAE,EAAE,GAAG,EAAS,CAAC,CAAA;QAC/D,OAAO,OAAO,CAAC,GAAG,CAAC,CAAA;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,GAAG,CAAC,CAAA;IACpB,CAAC;AACH,CAAC;AAED;;;GAGG;AACI,KAAK,wBAAyB,MAAoB,EAAE,GAAW;IACpE,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,GAAG,GAAQ,MAAM,MAAM,CAAC,OAAO,CAAC,cAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,GAAG,EAAS,CAAC,CAAA;QAClF,IAAI,GAAG,IAAI,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,IAAI,GAAG,cAAc,CAAC,CAAA;QACvD,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAA;IACzF,CAAC;IACD,MAAM,GAAG,GAAQ,MAAM,MAAM,CAAC,OAAO,CAAC,qCAA4C,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAS,CAAC,CAAA;IAC7G,MAAM,GAAG,GAAQ,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,gCAAuC,EAAE,EAAE,UAAU,EAAE,GAAG,EAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IACpI,MAAM,MAAM,GAAG,GAAG,EAAE,WAAW,IAAI,GAAG,EAAE,eAAe,CAAA;IACvD,IAAI,MAAM,IAAI,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,WAAW,GAAG,yEAAyE,CAAC,CAAA;IAC5H,MAAM,GAAG,GAAQ,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,GAAG,EAAS,CAAC,CAAA;IAClE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAA;AAC9F,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.planFromMarkup = planFromMarkup;
|
|
4
|
+
// Spec → issues: turn a document's structure into planned issues without an LLM round trip.
|
|
5
|
+
// Open checklist items become issues; without a checklist, the sections (lowest heading level
|
|
6
|
+
// that occurs more than once, else level 2/1) become issues with their text as description.
|
|
7
|
+
const markdown_1 = require("./markdown");
|
|
8
|
+
const CHECK = /^\s*\[( |x|X)\]\s+/;
|
|
9
|
+
function childrenOf(node) {
|
|
10
|
+
return Array.isArray(node?.content) ? node.content : [];
|
|
11
|
+
}
|
|
12
|
+
/** Open checklist items: Huly todo/task nodes, or "[ ] text" list items from Markdown imports. */
|
|
13
|
+
function checklist(root) {
|
|
14
|
+
const open = [];
|
|
15
|
+
let done = 0;
|
|
16
|
+
const walk = (node) => {
|
|
17
|
+
const type = String(node?.type ?? '');
|
|
18
|
+
if (type === 'todoItem' || type === 'taskItem') {
|
|
19
|
+
const [first, ...rest] = childrenOf(node);
|
|
20
|
+
const title = (0, markdown_1.extractText)(first ?? node).trim();
|
|
21
|
+
const nested = rest.map(markdown_1.extractText).join('\n').trim();
|
|
22
|
+
if (node.attrs?.checked === true)
|
|
23
|
+
done++;
|
|
24
|
+
else if (title !== '')
|
|
25
|
+
open.push({ title, description: nested !== '' ? nested : undefined });
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (type === 'listItem') {
|
|
29
|
+
const [first, ...rest] = childrenOf(node);
|
|
30
|
+
const text = (0, markdown_1.extractText)(first ?? node).trim();
|
|
31
|
+
const m = CHECK.exec(text);
|
|
32
|
+
if (m != null) {
|
|
33
|
+
const nested = rest.map(markdown_1.extractText).join('\n').trim();
|
|
34
|
+
if (m[1] !== ' ')
|
|
35
|
+
done++;
|
|
36
|
+
else
|
|
37
|
+
open.push({ title: text.replace(CHECK, '').trim(), description: nested !== '' ? nested : undefined });
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
for (const c of childrenOf(node))
|
|
42
|
+
walk(c);
|
|
43
|
+
};
|
|
44
|
+
walk(root);
|
|
45
|
+
return { open, done };
|
|
46
|
+
}
|
|
47
|
+
function headings(root) {
|
|
48
|
+
const blocks = childrenOf(root);
|
|
49
|
+
const levels = blocks.filter((b) => b?.type === 'heading').map((b) => Number(b.attrs?.level ?? 1));
|
|
50
|
+
if (levels.length === 0)
|
|
51
|
+
return [];
|
|
52
|
+
const count = (l) => levels.filter((x) => x === l).length;
|
|
53
|
+
// Sections are the most common heading level among 2/3; a single H1 is usually the title.
|
|
54
|
+
const level = [2, 3, 1].find((l) => count(l) > 1) ?? [2, 3, 1].find((l) => count(l) > 0) ?? levels[0];
|
|
55
|
+
const tasks = [];
|
|
56
|
+
let current;
|
|
57
|
+
const flush = () => {
|
|
58
|
+
if (current == null)
|
|
59
|
+
return;
|
|
60
|
+
const body = current.body.join('\n').trim();
|
|
61
|
+
tasks.push({ title: current.title, description: body !== '' ? body.slice(0, 2000) : undefined });
|
|
62
|
+
};
|
|
63
|
+
for (const b of blocks) {
|
|
64
|
+
if (b?.type === 'heading') {
|
|
65
|
+
const l = Number(b.attrs?.level ?? 1);
|
|
66
|
+
if (l === level) {
|
|
67
|
+
flush();
|
|
68
|
+
current = { title: (0, markdown_1.extractText)(b).trim(), body: [] };
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (l < level) {
|
|
72
|
+
flush();
|
|
73
|
+
current = undefined;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (current != null)
|
|
78
|
+
current.body.push((0, markdown_1.extractText)(b));
|
|
79
|
+
}
|
|
80
|
+
flush();
|
|
81
|
+
return tasks.filter((t) => t.title !== '');
|
|
82
|
+
}
|
|
83
|
+
function planFromMarkup(root) {
|
|
84
|
+
const list = checklist(root);
|
|
85
|
+
if (list.open.length > 0 || list.done > 0)
|
|
86
|
+
return { source: 'checklist', tasks: list.open, skippedDone: list.done };
|
|
87
|
+
const secs = headings(root);
|
|
88
|
+
return { source: secs.length > 0 ? 'headings' : 'none', tasks: secs, skippedDone: 0 };
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/utils/spec.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/storage.js
CHANGED
|
@@ -24,6 +24,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
24
24
|
exports.uploadMarkupBlob = uploadMarkupBlob;
|
|
25
25
|
exports.uploadBlob = uploadBlob;
|
|
26
26
|
exports.deleteBlob = deleteBlob;
|
|
27
|
+
/** Uploads can be large files; without a limit a stalled connection hangs the tool call. */
|
|
28
|
+
const UPLOAD_TIMEOUT_MS = 120_000;
|
|
27
29
|
const CLOUD_DATALAKE_URL = 'https://dl-eu.huly.app';
|
|
28
30
|
async function uploadMarkupBlob(wsToken, workspaceUuid, blobId, content) {
|
|
29
31
|
const result = await uploadBlob(wsToken, workspaceUuid, blobId, new Blob([content], { type: 'application/json' }));
|
|
@@ -43,7 +45,8 @@ async function uploadViaSelfHostedFront(frontUrl, wsToken, blobId, blob) {
|
|
|
43
45
|
const uploadRes = await fetch(uploadUrl, {
|
|
44
46
|
method: 'POST',
|
|
45
47
|
headers: { Authorization: `Bearer ${wsToken}` },
|
|
46
|
-
body: form
|
|
48
|
+
body: form,
|
|
49
|
+
signal: AbortSignal.timeout(UPLOAD_TIMEOUT_MS)
|
|
47
50
|
});
|
|
48
51
|
if (!uploadRes.ok) {
|
|
49
52
|
const body = await uploadRes.text().catch(() => '');
|
|
@@ -63,7 +66,8 @@ async function uploadViaCloudDatalake(workspaceUuid, wsToken, blobId, blob) {
|
|
|
63
66
|
const uploadRes = await fetch(uploadUrl, {
|
|
64
67
|
method: 'POST',
|
|
65
68
|
headers: { Authorization: `Bearer ${wsToken}` },
|
|
66
|
-
body: form
|
|
69
|
+
body: form,
|
|
70
|
+
signal: AbortSignal.timeout(UPLOAD_TIMEOUT_MS)
|
|
67
71
|
});
|
|
68
72
|
if (!uploadRes.ok) {
|
|
69
73
|
const body = await uploadRes.text().catch(() => '');
|
|
@@ -77,6 +81,6 @@ async function deleteBlob(wsToken, workspaceUuid, blobId) {
|
|
|
77
81
|
const url = frontUrl != null && frontUrl !== ''
|
|
78
82
|
? `${frontUrl.replace(/\/$/, '')}/files?file=${encodeURIComponent(blobId)}`
|
|
79
83
|
: `${CLOUD_DATALAKE_URL}/blob/${encodeURIComponent(workspaceUuid)}/${encodeURIComponent(blobId)}`;
|
|
80
|
-
await fetch(url, { method: 'DELETE', headers: { Authorization: `Bearer ${wsToken}` } }).catch(() => { });
|
|
84
|
+
await fetch(url, { method: 'DELETE', headers: { Authorization: `Bearer ${wsToken}` }, signal: AbortSignal.timeout(30_000) }).catch(() => { });
|
|
81
85
|
}
|
|
82
86
|
//# sourceMappingURL=storage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/utils/storage.ts"],"names":[],"mappings":";AAAA,uEAAuE;AACvE,qDAAqD;AACrD,EAAE;AACF,2DAA2D;AAC3D,qEAAqE;AACrE,gFAAgF;AAChF,yEAAyE;AACzE,EAAE;AACF,0EAA0E;AAC1E,wEAAwE;AACxE,kEAAkE;AAClE,8DAA8D;AAC9D,iFAAiF;AACjF,iCAAiC;AACjC,4CAA4C;AAC5C,mEAAmE;AACnE,EAAE;AACF,uEAAuE;AACvE,0EAA0E;AAC1E,sEAAsE;AACtE,iEAAiE
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/utils/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Next number from the core Sequence of a class ($inc like Huly's create dialogs). */
|
|
2
|
+
export declare function nextNumber(client: any, cls: string): Promise<number>;
|
|
3
|
+
export interface Workflow {
|
|
4
|
+
kind: string;
|
|
5
|
+
statuses: Array<{
|
|
6
|
+
_id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
category?: string;
|
|
9
|
+
}>;
|
|
10
|
+
}
|
|
11
|
+
/** Task type and ordered statuses of a project-like space (vacancy, funnel). */
|
|
12
|
+
export declare function workflowOf(client: any, space: any): Promise<Workflow>;
|
|
13
|
+
export declare function pickStatus(wf: Workflow, name?: string): string;
|
|
14
|
+
export declare const statusName: (wf: Workflow, id: string) => string;
|
|
15
|
+
/** Display name of a person ("Last,First") or organization. */
|
|
16
|
+
export declare const contactName: (c: any) => string;
|
|
17
|
+
/** Finds one contact (person or organization) by id or name, optionally of one class. */
|
|
18
|
+
export declare function findContact(client: any, ref: string, cls?: string): Promise<any>;
|
|
19
|
+
/** Finds one space-like doc of a class by id or (case-insensitive) name. */
|
|
20
|
+
export declare function findNamed(client: any, cls: string, ref: string, what: string, query?: Record<string, unknown>): Promise<any>;
|
|
21
|
+
/** "2026-06-01" → timestamp (local midnight); throws on bad input. */
|
|
22
|
+
export declare function parseDay(value: string, field: string): number;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.contactName = exports.statusName = void 0;
|
|
4
|
+
exports.nextNumber = nextNumber;
|
|
5
|
+
exports.workflowOf = workflowOf;
|
|
6
|
+
exports.pickStatus = pickStatus;
|
|
7
|
+
exports.findContact = findContact;
|
|
8
|
+
exports.findNamed = findNamed;
|
|
9
|
+
exports.parseDay = parseDay;
|
|
10
|
+
// Helpers for task-like documents outside the tracker (applicants, leads): numbering, workflows,
|
|
11
|
+
// contacts. They follow how Huly's own create dialogs write (see recruit/lead resources).
|
|
12
|
+
const people_1 = require("./people");
|
|
13
|
+
/** Next number from the core Sequence of a class ($inc like Huly's create dialogs). */
|
|
14
|
+
async function nextNumber(client, cls) {
|
|
15
|
+
const seq = await client.findOne('core:class:Sequence', { attachedTo: cls });
|
|
16
|
+
if (seq == null)
|
|
17
|
+
throw new Error(`No number sequence for ${cls} — is the module enabled in this workspace?`);
|
|
18
|
+
const res = await client.update(seq, { $inc: { sequence: 1 } }, true);
|
|
19
|
+
return res?.object?.sequence ?? (Number(seq.sequence ?? 0) + 1);
|
|
20
|
+
}
|
|
21
|
+
/** Task type and ordered statuses of a project-like space (vacancy, funnel). */
|
|
22
|
+
async function workflowOf(client, space) {
|
|
23
|
+
const type = await client.findOne('task:class:ProjectType', { _id: space.type });
|
|
24
|
+
const kind = type?.tasks?.[0];
|
|
25
|
+
if (kind == null)
|
|
26
|
+
throw new Error(`'${String(space.name)}' has no task type.`);
|
|
27
|
+
const taskType = await client.findOne('task:class:TaskType', { _id: kind });
|
|
28
|
+
const ids = taskType?.statuses ?? [];
|
|
29
|
+
const docs = await client.findAll('core:class:Status', { _id: { $in: ids } });
|
|
30
|
+
const statuses = ids.map((id) => docs.find((d) => d._id === id)).filter((d) => d != null).map((d) => ({ _id: d._id, name: d.name, category: d.category }));
|
|
31
|
+
return { kind, statuses };
|
|
32
|
+
}
|
|
33
|
+
function pickStatus(wf, name) {
|
|
34
|
+
if (name == null) {
|
|
35
|
+
if (wf.statuses.length === 0)
|
|
36
|
+
throw new Error('This workflow has no statuses.');
|
|
37
|
+
return wf.statuses[0]._id;
|
|
38
|
+
}
|
|
39
|
+
const hit = wf.statuses.find((s) => s.name.toLowerCase() === name.trim().toLowerCase());
|
|
40
|
+
if (hit == null)
|
|
41
|
+
throw new Error(`Status '${name}' not found. Available: ${wf.statuses.map((s) => s.name).join(', ')}.`);
|
|
42
|
+
return hit._id;
|
|
43
|
+
}
|
|
44
|
+
const statusName = (wf, id) => wf.statuses.find((s) => s._id === id)?.name ?? '?';
|
|
45
|
+
exports.statusName = statusName;
|
|
46
|
+
/** Display name of a person ("Last,First") or organization. */
|
|
47
|
+
const contactName = (c) => c == null ? '—' : c._class === 'contact:class:Organization' ? String(c.name ?? '') : (0, people_1.formatPersonName)(c.name);
|
|
48
|
+
exports.contactName = contactName;
|
|
49
|
+
/** Finds one contact (person or organization) by id or name, optionally of one class. */
|
|
50
|
+
async function findContact(client, ref, cls = 'contact:class:Contact') {
|
|
51
|
+
const byId = await client.findOne(cls, { _id: ref });
|
|
52
|
+
if (byId != null)
|
|
53
|
+
return byId;
|
|
54
|
+
const all = await client.findAll(cls, {});
|
|
55
|
+
const q = ref.trim().toLowerCase();
|
|
56
|
+
const exact = all.filter((c) => (0, exports.contactName)(c).toLowerCase() === q || String(c.name ?? '').toLowerCase() === q);
|
|
57
|
+
const hits = exact.length > 0 ? exact : all.filter((c) => (0, exports.contactName)(c).toLowerCase().includes(q));
|
|
58
|
+
if (hits.length === 1)
|
|
59
|
+
return hits[0];
|
|
60
|
+
if (hits.length === 0)
|
|
61
|
+
throw new Error(`Contact '${ref}' not found.`);
|
|
62
|
+
throw new Error(`Contact '${ref}' is ambiguous: ${hits.slice(0, 8).map(exports.contactName).join(', ')}.`);
|
|
63
|
+
}
|
|
64
|
+
/** Finds one space-like doc of a class by id or (case-insensitive) name. */
|
|
65
|
+
async function findNamed(client, cls, ref, what, query = {}) {
|
|
66
|
+
const all = await client.findAll(cls, query);
|
|
67
|
+
const hits = all.filter((d) => d._id === ref || String(d.name ?? d.title ?? '').toLowerCase() === ref.trim().toLowerCase());
|
|
68
|
+
if (hits.length === 1)
|
|
69
|
+
return hits[0];
|
|
70
|
+
if (hits.length === 0)
|
|
71
|
+
throw new Error(`${what} '${ref}' not found. Available: ${all.map((d) => d.name ?? d.title).slice(0, 15).join(', ') || 'none'}.`);
|
|
72
|
+
throw new Error(`${what} '${ref}' is ambiguous — pass its id.`);
|
|
73
|
+
}
|
|
74
|
+
/** "2026-06-01" → timestamp (local midnight); throws on bad input. */
|
|
75
|
+
function parseDay(value, field) {
|
|
76
|
+
const t = Date.parse(value);
|
|
77
|
+
if (Number.isNaN(t))
|
|
78
|
+
throw new Error(`${field} must be a date (YYYY-MM-DD), got '${value}'.`);
|
|
79
|
+
return t;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=tasks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/utils/tasks.ts"],"names":[],"mappings":"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"}
|
package/dist/watch.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export declare const DEFAULT_COMMAND = "claude -p {prompt} --mcp-config {mcpConfig} --strict-mcp-config --allowedTools mcp__huly --permission-mode acceptEdits";
|
|
2
|
+
export declare const DEFAULT_PROMPT: string;
|
|
3
|
+
export interface WatchOptions {
|
|
4
|
+
workspace?: string;
|
|
5
|
+
projects: string[];
|
|
6
|
+
label?: string;
|
|
7
|
+
assigned: boolean;
|
|
8
|
+
command: string;
|
|
9
|
+
prompt: string;
|
|
10
|
+
cwd: string;
|
|
11
|
+
intervalSec: number;
|
|
12
|
+
once: boolean;
|
|
13
|
+
dryRun: boolean;
|
|
14
|
+
statePath?: string;
|
|
15
|
+
timeoutMin: number;
|
|
16
|
+
agent: string;
|
|
17
|
+
envFile?: string;
|
|
18
|
+
/** Script that starts this MCP server (for {mcpConfig}); defaults to the running script. */
|
|
19
|
+
serverEntry?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare const WATCH_HELP = "Usage: huly-mcp watch [options]\n\nHands Huly issues to an agent: open issues with --label, or assigned to this account\n(--assigned, the default), are claimed, passed to --command and released afterwards.\n\n --workspace <ws> Workspace slug/name (required with more than one)\n --project <KEY> Only these projects (repeat or comma-separate); default: all,\n limited to HULY_WRITE_PROJECTS when set\n --label <name> Trigger label (e.g. \"claude\")\n --assigned Trigger: assigned to this account (default if no --label)\n --command <cmd> Command per issue; placeholders {prompt} {issue} {title}\n {workspace} {agent} {trigger} {mcpConfig}\n default: claude -p {prompt} --mcp-config {mcpConfig} --strict-mcp-config --allowedTools mcp__huly --permission-mode acceptEdits\n --prompt <text> Prompt template (same placeholders, except {prompt})\n --cwd <dir> Working directory for the command (default: current)\n --interval <sec> Poll interval (default 60)\n --timeout <min> Stop a run after this many minutes (default 60)\n --once One pass, then exit\n --dry-run Only list what would run\n --state <file> State file (default ~/.huly-mcp/watch-<workspace>.json)\n --agent <name> Agent name for claims (default HULY_AGENT_NAME or claude-watch)\n --env-file <file> Load HULY_* credentials from this file (the agent's own account)\n";
|
|
22
|
+
/** Splits a command line into words; supports "double" and 'single' quotes. No shell involved. */
|
|
23
|
+
export declare function splitCommand(line: string): string[];
|
|
24
|
+
/** Replaces {name} placeholders. Unknown placeholders stay as they are. */
|
|
25
|
+
export declare function fill(template: string, vars: Record<string, string>): string;
|
|
26
|
+
/** KEY=value lines (comments, export prefix and quotes allowed). */
|
|
27
|
+
export declare function parseEnvFile(content: string): Record<string, string>;
|
|
28
|
+
export declare function parseWatchArgs(argv: string[], env?: NodeJS.ProcessEnv): WatchOptions;
|
|
29
|
+
export interface RunRecord {
|
|
30
|
+
identifier: string;
|
|
31
|
+
trigger: string;
|
|
32
|
+
ranAt: number;
|
|
33
|
+
result: string;
|
|
34
|
+
}
|
|
35
|
+
export type WatchState = Record<string, RunRecord>;
|
|
36
|
+
export declare function loadState(path: string): WatchState;
|
|
37
|
+
export declare function saveState(path: string, state: WatchState): void;
|
|
38
|
+
export interface Candidate {
|
|
39
|
+
issue: any;
|
|
40
|
+
trigger: 'label' | 'assigned';
|
|
41
|
+
since: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Open issues that match a trigger and have not run yet. An issue runs again only when its
|
|
45
|
+
* trigger label was added again after the last run (remove + add the label to retry).
|
|
46
|
+
*/
|
|
47
|
+
export declare function findCandidates(client: any, opts: Pick<WatchOptions, 'projects' | 'label' | 'assigned'>, state: WatchState): Promise<Candidate[]>;
|
|
48
|
+
export interface RunDeps {
|
|
49
|
+
client: any;
|
|
50
|
+
workspace: string;
|
|
51
|
+
/** Runs argv in cwd with env; resolves with the exit code (null when killed). */
|
|
52
|
+
exec: (argv: string[], cwd: string, env: NodeJS.ProcessEnv, timeoutMs: number) => Promise<number | null>;
|
|
53
|
+
log: (line: string) => void;
|
|
54
|
+
env: NodeJS.ProcessEnv;
|
|
55
|
+
now?: () => number;
|
|
56
|
+
}
|
|
57
|
+
/** MCP config for the child Claude: this server, same credentials (inherited env), one workspace. */
|
|
58
|
+
export declare function writeMcpConfig(dir: string, entry: string, env: Record<string, string>): string;
|
|
59
|
+
export declare function processIssue(c: Candidate, opts: WatchOptions, deps: RunDeps): Promise<RunRecord | undefined>;
|
|
60
|
+
/** One poll: find candidates and run them one after another. */
|
|
61
|
+
export declare function watchOnce(opts: WatchOptions, deps: RunDeps, state: WatchState, save: (s: WatchState) => void): Promise<number>;
|
|
62
|
+
export declare function runWatch(argv: string[]): Promise<void>;
|