huly-mcp-selfhost 3.3.0 → 3.5.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 +11 -0
- package/CHANGELOG.md +22 -0
- package/README.md +126 -17
- package/dist/guides/costs.md +2 -1
- package/dist/guides/workflow.md +3 -1
- package/dist/index.js +105034 -46
- package/dist/setup.js +4 -0
- package/package.json +12 -11
- package/dist/connection.d.ts +0 -78
- package/dist/connection.js +0 -271
- package/dist/connection.js.map +0 -1
- package/dist/env.d.ts +0 -1
- package/dist/env.js +0 -17
- package/dist/env.js.map +0 -1
- package/dist/guard.d.ts +0 -39
- package/dist/guard.js +0 -165
- package/dist/guard.js.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js.map +0 -1
- package/dist/junit-cli.d.ts +0 -8
- package/dist/junit-cli.js +0 -106
- package/dist/junit-cli.js.map +0 -1
- package/dist/registry.d.ts +0 -18
- package/dist/registry.js +0 -318
- package/dist/registry.js.map +0 -1
- package/dist/resources.d.ts +0 -19
- package/dist/resources.js +0 -255
- package/dist/resources.js.map +0 -1
- package/dist/schemas.d.ts +0 -1559
- package/dist/schemas.js +0 -1086
- package/dist/schemas.js.map +0 -1
- package/dist/server.d.ts +0 -29
- package/dist/server.js +0 -215
- package/dist/server.js.map +0 -1
- package/dist/tools/activity.d.ts +0 -10
- package/dist/tools/activity.js +0 -62
- package/dist/tools/activity.js.map +0 -1
- package/dist/tools/agent.d.ts +0 -156
- package/dist/tools/agent.js +0 -523
- package/dist/tools/agent.js.map +0 -1
- package/dist/tools/attachments.d.ts +0 -31
- package/dist/tools/attachments.js +0 -61
- package/dist/tools/attachments.js.map +0 -1
- package/dist/tools/calendar.d.ts +0 -49
- package/dist/tools/calendar.js +0 -116
- package/dist/tools/calendar.js.map +0 -1
- package/dist/tools/cards.d.ts +0 -87
- package/dist/tools/cards.js +0 -246
- package/dist/tools/cards.js.map +0 -1
- package/dist/tools/channels.d.ts +0 -118
- package/dist/tools/channels.js +0 -211
- package/dist/tools/channels.js.map +0 -1
- package/dist/tools/comments.d.ts +0 -42
- package/dist/tools/comments.js +0 -77
- package/dist/tools/comments.js.map +0 -1
- package/dist/tools/components.d.ts +0 -45
- package/dist/tools/components.js +0 -107
- package/dist/tools/components.js.map +0 -1
- package/dist/tools/contacts.d.ts +0 -69
- package/dist/tools/contacts.js +0 -130
- package/dist/tools/contacts.js.map +0 -1
- package/dist/tools/crm.d.ts +0 -61
- package/dist/tools/crm.js +0 -117
- package/dist/tools/crm.js.map +0 -1
- package/dist/tools/documents.d.ts +0 -100
- package/dist/tools/documents.js +0 -294
- package/dist/tools/documents.js.map +0 -1
- package/dist/tools/drive.d.ts +0 -107
- package/dist/tools/drive.js +0 -277
- package/dist/tools/drive.js.map +0 -1
- package/dist/tools/fields.d.ts +0 -33
- package/dist/tools/fields.js +0 -124
- package/dist/tools/fields.js.map +0 -1
- package/dist/tools/generic.d.ts +0 -72
- package/dist/tools/generic.js +0 -242
- package/dist/tools/generic.js.map +0 -1
- package/dist/tools/github.d.ts +0 -21
- package/dist/tools/github.js +0 -80
- package/dist/tools/github.js.map +0 -1
- package/dist/tools/hr.d.ts +0 -97
- package/dist/tools/hr.js +0 -150
- package/dist/tools/hr.js.map +0 -1
- package/dist/tools/inbox.d.ts +0 -23
- package/dist/tools/inbox.js +0 -76
- package/dist/tools/inbox.js.map +0 -1
- package/dist/tools/inventory.d.ts +0 -61
- package/dist/tools/inventory.js +0 -103
- package/dist/tools/inventory.js.map +0 -1
- package/dist/tools/issues.d.ts +0 -112
- package/dist/tools/issues.js +0 -474
- package/dist/tools/issues.js.map +0 -1
- package/dist/tools/labels.d.ts +0 -87
- package/dist/tools/labels.js +0 -232
- package/dist/tools/labels.js.map +0 -1
- package/dist/tools/log-time.d.ts +0 -25
- package/dist/tools/log-time.js +0 -95
- package/dist/tools/log-time.js.map +0 -1
- package/dist/tools/meetings.d.ts +0 -30
- package/dist/tools/meetings.js +0 -78
- package/dist/tools/meetings.js.map +0 -1
- package/dist/tools/members.d.ts +0 -8
- package/dist/tools/members.js +0 -33
- package/dist/tools/members.js.map +0 -1
- package/dist/tools/message-templates.d.ts +0 -54
- package/dist/tools/message-templates.js +0 -88
- package/dist/tools/message-templates.js.map +0 -1
- package/dist/tools/milestones.d.ts +0 -56
- package/dist/tools/milestones.js +0 -172
- package/dist/tools/milestones.js.map +0 -1
- package/dist/tools/organizations.d.ts +0 -37
- package/dist/tools/organizations.js +0 -88
- package/dist/tools/organizations.js.map +0 -1
- package/dist/tools/overview.d.ts +0 -55
- package/dist/tools/overview.js +0 -395
- package/dist/tools/overview.js.map +0 -1
- package/dist/tools/planner.d.ts +0 -60
- package/dist/tools/planner.js +0 -145
- package/dist/tools/planner.js.map +0 -1
- package/dist/tools/process.d.ts +0 -50
- package/dist/tools/process.js +0 -137
- package/dist/tools/process.js.map +0 -1
- package/dist/tools/products.d.ts +0 -17
- package/dist/tools/products.js +0 -45
- package/dist/tools/products.js.map +0 -1
- package/dist/tools/projects.d.ts +0 -41
- package/dist/tools/projects.js +0 -93
- package/dist/tools/projects.js.map +0 -1
- package/dist/tools/qms.d.ts +0 -57
- package/dist/tools/qms.js +0 -171
- package/dist/tools/qms.js.map +0 -1
- package/dist/tools/recruiting.d.ts +0 -112
- package/dist/tools/recruiting.js +0 -203
- package/dist/tools/recruiting.js.map +0 -1
- package/dist/tools/relations.d.ts +0 -72
- package/dist/tools/relations.js +0 -192
- package/dist/tools/relations.js.map +0 -1
- package/dist/tools/search.d.ts +0 -23
- package/dist/tools/search.js +0 -60
- package/dist/tools/search.js.map +0 -1
- package/dist/tools/sharing.d.ts +0 -62
- package/dist/tools/sharing.js +0 -149
- package/dist/tools/sharing.js.map +0 -1
- package/dist/tools/statuses.d.ts +0 -19
- package/dist/tools/statuses.js +0 -93
- package/dist/tools/statuses.js.map +0 -1
- package/dist/tools/surveys.d.ts +0 -22
- package/dist/tools/surveys.js +0 -53
- package/dist/tools/surveys.js.map +0 -1
- package/dist/tools/templates.d.ts +0 -95
- package/dist/tools/templates.js +0 -260
- package/dist/tools/templates.js.map +0 -1
- package/dist/tools/test-automation.d.ts +0 -81
- package/dist/tools/test-automation.js +0 -225
- package/dist/tools/test-automation.js.map +0 -1
- package/dist/tools/testing.d.ts +0 -234
- package/dist/tools/testing.js +0 -401
- package/dist/tools/testing.js.map +0 -1
- package/dist/tools/workspace-admin.d.ts +0 -55
- package/dist/tools/workspace-admin.js +0 -117
- package/dist/tools/workspace-admin.js.map +0 -1
- package/dist/tools/workspaces.d.ts +0 -6
- package/dist/tools/workspaces.js +0 -19
- package/dist/tools/workspaces.js.map +0 -1
- package/dist/utils/attributes.d.ts +0 -37
- package/dist/utils/attributes.js +0 -188
- package/dist/utils/attributes.js.map +0 -1
- package/dist/utils/classes.d.ts +0 -51
- package/dist/utils/classes.js +0 -73
- package/dist/utils/classes.js.map +0 -1
- package/dist/utils/content.d.ts +0 -11
- package/dist/utils/content.js +0 -86
- package/dist/utils/content.js.map +0 -1
- package/dist/utils/errors.d.ts +0 -11
- package/dist/utils/errors.js +0 -24
- package/dist/utils/errors.js.map +0 -1
- package/dist/utils/files.d.ts +0 -5
- package/dist/utils/files.js +0 -50
- package/dist/utils/files.js.map +0 -1
- package/dist/utils/format.d.ts +0 -8
- package/dist/utils/format.js +0 -57
- package/dist/utils/format.js.map +0 -1
- package/dist/utils/junit.d.ts +0 -13
- package/dist/utils/junit.js +0 -81
- package/dist/utils/junit.js.map +0 -1
- package/dist/utils/markdown.d.ts +0 -14
- package/dist/utils/markdown.js +0 -149
- package/dist/utils/markdown.js.map +0 -1
- package/dist/utils/meeting.d.ts +0 -13
- package/dist/utils/meeting.js +0 -118
- package/dist/utils/meeting.js.map +0 -1
- package/dist/utils/people.d.ts +0 -25
- package/dist/utils/people.js +0 -80
- package/dist/utils/people.js.map +0 -1
- package/dist/utils/redact.d.ts +0 -3
- package/dist/utils/redact.js +0 -26
- package/dist/utils/redact.js.map +0 -1
- package/dist/utils/resolve.d.ts +0 -17
- package/dist/utils/resolve.js +0 -54
- package/dist/utils/resolve.js.map +0 -1
- package/dist/utils/spec.d.ts +0 -10
- package/dist/utils/spec.js +0 -90
- package/dist/utils/spec.js.map +0 -1
- package/dist/utils/storage.d.ts +0 -7
- package/dist/utils/storage.js +0 -86
- package/dist/utils/storage.js.map +0 -1
- package/dist/utils/tasks.d.ts +0 -22
- package/dist/utils/tasks.js +0 -81
- package/dist/utils/tasks.js.map +0 -1
- package/dist/watch.d.ts +0 -62
- package/dist/watch.js +0 -405
- package/dist/watch.js.map +0 -1
- package/scripts/cleanup-issues.js +0 -141
- package/scripts/copy-guides.js +0 -18
- package/scripts/demo.js +0 -201
- package/scripts/import-csv.js +0 -250
- package/scripts/sample-tasks.csv +0 -11
- package/scripts/setup.js +0 -163
package/dist/watch.js
DELETED
|
@@ -1,405 +0,0 @@
|
|
|
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.WATCH_HELP = exports.DEFAULT_PROMPT = exports.DEFAULT_COMMAND = void 0;
|
|
7
|
-
exports.splitCommand = splitCommand;
|
|
8
|
-
exports.fill = fill;
|
|
9
|
-
exports.parseEnvFile = parseEnvFile;
|
|
10
|
-
exports.parseWatchArgs = parseWatchArgs;
|
|
11
|
-
exports.loadState = loadState;
|
|
12
|
-
exports.saveState = saveState;
|
|
13
|
-
exports.findCandidates = findCandidates;
|
|
14
|
-
exports.writeMcpConfig = writeMcpConfig;
|
|
15
|
-
exports.processIssue = processIssue;
|
|
16
|
-
exports.watchOnce = watchOnce;
|
|
17
|
-
exports.runWatch = runWatch;
|
|
18
|
-
// `huly-mcp watch`: Huly hands work to an agent.
|
|
19
|
-
// Polls for open issues that carry a trigger label or are assigned to the connected account,
|
|
20
|
-
// claims each one (claim_issue), runs a command for it — by default `claude -p` — and releases
|
|
21
|
-
// the claim afterwards. A state file remembers which issues already ran.
|
|
22
|
-
const node_child_process_1 = require("node:child_process");
|
|
23
|
-
const node_fs_1 = require("node:fs");
|
|
24
|
-
const node_os_1 = require("node:os");
|
|
25
|
-
const node_path_1 = require("node:path");
|
|
26
|
-
const tracker_1 = __importDefault(require("@hcengineering/tracker"));
|
|
27
|
-
const task_1 = __importDefault(require("@hcengineering/task"));
|
|
28
|
-
const connection_1 = require("./connection");
|
|
29
|
-
const env_1 = require("./env");
|
|
30
|
-
const guard_1 = require("./guard");
|
|
31
|
-
const people_1 = require("./utils/people");
|
|
32
|
-
const agent_1 = require("./tools/agent");
|
|
33
|
-
const comments_1 = require("./tools/comments");
|
|
34
|
-
exports.DEFAULT_COMMAND = 'claude -p {prompt} --mcp-config {mcpConfig} --strict-mcp-config --allowedTools mcp__huly --permission-mode acceptEdits';
|
|
35
|
-
exports.DEFAULT_PROMPT = [
|
|
36
|
-
'Huly issue {issue} ("{title}") in workspace {workspace} was handed to you ({trigger}).',
|
|
37
|
-
'You are the Huly agent "{agent}" and already hold the claim on it.',
|
|
38
|
-
'1. Read everything with get_issue_context {issue}.',
|
|
39
|
-
'2. Do the work in the current directory.',
|
|
40
|
-
'3. Hand back with finish_work: a short summary of what you did and what is left.',
|
|
41
|
-
'If you cannot finish, add a comment that says what is missing, then stop. Never delete anything.'
|
|
42
|
-
].join('\n');
|
|
43
|
-
exports.WATCH_HELP = `Usage: huly-mcp watch [options]
|
|
44
|
-
|
|
45
|
-
Hands Huly issues to an agent: open issues with --label, or assigned to this account
|
|
46
|
-
(--assigned, the default), are claimed, passed to --command and released afterwards.
|
|
47
|
-
|
|
48
|
-
--workspace <ws> Workspace slug/name (required with more than one)
|
|
49
|
-
--project <KEY> Only these projects (repeat or comma-separate); default: all,
|
|
50
|
-
limited to HULY_WRITE_PROJECTS when set
|
|
51
|
-
--label <name> Trigger label (e.g. "claude")
|
|
52
|
-
--assigned Trigger: assigned to this account (default if no --label)
|
|
53
|
-
--command <cmd> Command per issue; placeholders {prompt} {issue} {title}
|
|
54
|
-
{workspace} {agent} {trigger} {mcpConfig}
|
|
55
|
-
default: ${exports.DEFAULT_COMMAND}
|
|
56
|
-
--prompt <text> Prompt template (same placeholders, except {prompt})
|
|
57
|
-
--cwd <dir> Working directory for the command (default: current)
|
|
58
|
-
--interval <sec> Poll interval (default 60)
|
|
59
|
-
--timeout <min> Stop a run after this many minutes (default 60)
|
|
60
|
-
--once One pass, then exit
|
|
61
|
-
--dry-run Only list what would run
|
|
62
|
-
--state <file> State file (default ~/.huly-mcp/watch-<workspace>.json)
|
|
63
|
-
--agent <name> Agent name for claims (default HULY_AGENT_NAME or claude-watch)
|
|
64
|
-
--env-file <file> Load HULY_* credentials from this file (the agent's own account)
|
|
65
|
-
`;
|
|
66
|
-
/** Splits a command line into words; supports "double" and 'single' quotes. No shell involved. */
|
|
67
|
-
function splitCommand(line) {
|
|
68
|
-
const out = [];
|
|
69
|
-
let cur = '';
|
|
70
|
-
let quote = null;
|
|
71
|
-
let started = false;
|
|
72
|
-
for (const ch of line) {
|
|
73
|
-
if (quote != null) {
|
|
74
|
-
if (ch === quote)
|
|
75
|
-
quote = null;
|
|
76
|
-
else
|
|
77
|
-
cur += ch;
|
|
78
|
-
}
|
|
79
|
-
else if (ch === '"' || ch === "'") {
|
|
80
|
-
quote = ch;
|
|
81
|
-
started = true;
|
|
82
|
-
}
|
|
83
|
-
else if (/\s/.test(ch)) {
|
|
84
|
-
if (started || cur !== '')
|
|
85
|
-
out.push(cur);
|
|
86
|
-
cur = '';
|
|
87
|
-
started = false;
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
cur += ch;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
if (quote != null)
|
|
94
|
-
throw new Error(`Unclosed ${quote} in --command.`);
|
|
95
|
-
if (started || cur !== '')
|
|
96
|
-
out.push(cur);
|
|
97
|
-
return out;
|
|
98
|
-
}
|
|
99
|
-
/** Replaces {name} placeholders. Unknown placeholders stay as they are. */
|
|
100
|
-
function fill(template, vars) {
|
|
101
|
-
return template.replace(/\{(\w+)\}/g, (m, k) => vars[k] ?? m);
|
|
102
|
-
}
|
|
103
|
-
/** KEY=value lines (comments, export prefix and quotes allowed). */
|
|
104
|
-
function parseEnvFile(content) {
|
|
105
|
-
const out = {};
|
|
106
|
-
for (const raw of content.split(/\r?\n/)) {
|
|
107
|
-
const line = raw.trim();
|
|
108
|
-
if (line === '' || line.startsWith('#'))
|
|
109
|
-
continue;
|
|
110
|
-
const m = /^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(line);
|
|
111
|
-
if (m == null)
|
|
112
|
-
continue;
|
|
113
|
-
let v = m[2].trim();
|
|
114
|
-
if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'")))
|
|
115
|
-
v = v.slice(1, -1);
|
|
116
|
-
else
|
|
117
|
-
v = v.replace(/\s+#.*$/, '');
|
|
118
|
-
out[m[1]] = v;
|
|
119
|
-
}
|
|
120
|
-
return out;
|
|
121
|
-
}
|
|
122
|
-
function parseWatchArgs(argv, env = process.env) {
|
|
123
|
-
const opts = {
|
|
124
|
-
projects: [],
|
|
125
|
-
assigned: false,
|
|
126
|
-
command: exports.DEFAULT_COMMAND,
|
|
127
|
-
prompt: exports.DEFAULT_PROMPT,
|
|
128
|
-
cwd: process.cwd(),
|
|
129
|
-
intervalSec: 60,
|
|
130
|
-
once: false,
|
|
131
|
-
dryRun: false,
|
|
132
|
-
timeoutMin: 60,
|
|
133
|
-
agent: env.HULY_AGENT_NAME ?? 'claude-watch'
|
|
134
|
-
};
|
|
135
|
-
const value = (i, flag) => {
|
|
136
|
-
const v = argv[i + 1];
|
|
137
|
-
if (v == null || v.startsWith('--'))
|
|
138
|
-
throw new Error(`${flag} needs a value.`);
|
|
139
|
-
return v;
|
|
140
|
-
};
|
|
141
|
-
const number = (v, flag, min) => {
|
|
142
|
-
const n = Number(v);
|
|
143
|
-
if (!Number.isFinite(n) || n < min)
|
|
144
|
-
throw new Error(`${flag} must be a number ≥ ${min}.`);
|
|
145
|
-
return n;
|
|
146
|
-
};
|
|
147
|
-
for (let i = 0; i < argv.length; i++) {
|
|
148
|
-
const flag = argv[i];
|
|
149
|
-
switch (flag) {
|
|
150
|
-
case '--workspace':
|
|
151
|
-
opts.workspace = value(i, flag);
|
|
152
|
-
i++;
|
|
153
|
-
break;
|
|
154
|
-
case '--project':
|
|
155
|
-
opts.projects.push(...value(i, flag).split(',').map((p) => p.trim().toUpperCase()).filter((p) => p !== ''));
|
|
156
|
-
i++;
|
|
157
|
-
break;
|
|
158
|
-
case '--label':
|
|
159
|
-
opts.label = value(i, flag);
|
|
160
|
-
i++;
|
|
161
|
-
break;
|
|
162
|
-
case '--assigned':
|
|
163
|
-
opts.assigned = true;
|
|
164
|
-
break;
|
|
165
|
-
case '--command':
|
|
166
|
-
opts.command = value(i, flag);
|
|
167
|
-
i++;
|
|
168
|
-
break;
|
|
169
|
-
case '--prompt':
|
|
170
|
-
opts.prompt = value(i, flag);
|
|
171
|
-
i++;
|
|
172
|
-
break;
|
|
173
|
-
case '--cwd':
|
|
174
|
-
opts.cwd = (0, node_path_1.resolve)(value(i, flag));
|
|
175
|
-
i++;
|
|
176
|
-
break;
|
|
177
|
-
case '--interval':
|
|
178
|
-
opts.intervalSec = number(value(i, flag), flag, 5);
|
|
179
|
-
i++;
|
|
180
|
-
break;
|
|
181
|
-
case '--timeout':
|
|
182
|
-
opts.timeoutMin = number(value(i, flag), flag, 1);
|
|
183
|
-
i++;
|
|
184
|
-
break;
|
|
185
|
-
case '--once':
|
|
186
|
-
opts.once = true;
|
|
187
|
-
break;
|
|
188
|
-
case '--dry-run':
|
|
189
|
-
opts.dryRun = true;
|
|
190
|
-
break;
|
|
191
|
-
case '--state':
|
|
192
|
-
opts.statePath = (0, node_path_1.resolve)(value(i, flag));
|
|
193
|
-
i++;
|
|
194
|
-
break;
|
|
195
|
-
case '--agent':
|
|
196
|
-
opts.agent = value(i, flag).replace(/\s+/g, '-');
|
|
197
|
-
i++;
|
|
198
|
-
break;
|
|
199
|
-
case '--env-file':
|
|
200
|
-
opts.envFile = (0, node_path_1.resolve)(value(i, flag));
|
|
201
|
-
i++;
|
|
202
|
-
break;
|
|
203
|
-
default: throw new Error(`Unknown option '${flag}'. See huly-mcp watch --help.`);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
if (opts.label == null)
|
|
207
|
-
opts.assigned = true;
|
|
208
|
-
if (splitCommand(opts.command).length === 0)
|
|
209
|
-
throw new Error('--command is empty.');
|
|
210
|
-
return opts;
|
|
211
|
-
}
|
|
212
|
-
function loadState(path) {
|
|
213
|
-
if (!(0, node_fs_1.existsSync)(path))
|
|
214
|
-
return {};
|
|
215
|
-
try {
|
|
216
|
-
return JSON.parse((0, node_fs_1.readFileSync)(path, 'utf8'));
|
|
217
|
-
}
|
|
218
|
-
catch {
|
|
219
|
-
throw new Error(`State file ${path} is not valid JSON — fix or delete it.`);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
function saveState(path, state) {
|
|
223
|
-
(0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(path), { recursive: true });
|
|
224
|
-
(0, node_fs_1.writeFileSync)(path, JSON.stringify(state, null, 2) + '\n');
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Open issues that match a trigger and have not run yet. An issue runs again only when its
|
|
228
|
-
* trigger label was added again after the last run (remove + add the label to retry).
|
|
229
|
-
*/
|
|
230
|
-
async function findCandidates(client, opts, state) {
|
|
231
|
-
const projects = await client.findAll(tracker_1.default.class.Project, opts.projects.length > 0 ? { identifier: { $in: opts.projects } } : {});
|
|
232
|
-
const missing = opts.projects.filter((p) => !projects.some((x) => x.identifier === p));
|
|
233
|
-
if (missing.length > 0)
|
|
234
|
-
throw new Error(`Project(s) not found: ${missing.join(', ')}.`);
|
|
235
|
-
const spaces = new Set(projects.map((p) => p._id));
|
|
236
|
-
const statuses = await client.findAll(tracker_1.default.class.IssueStatus, {});
|
|
237
|
-
const closed = new Set(statuses.filter((s) => s.category === task_1.default.statusCategory.Won || s.category === task_1.default.statusCategory.Lost).map((s) => s._id));
|
|
238
|
-
const open = (i) => spaces.has(i.space) && !closed.has(i.status);
|
|
239
|
-
const found = new Map();
|
|
240
|
-
if (opts.label != null) {
|
|
241
|
-
const want = opts.label.toLowerCase();
|
|
242
|
-
const refs = (await client.findAll('tags:class:TagReference', { attachedToClass: tracker_1.default.class.Issue }))
|
|
243
|
-
.filter((r) => String(r.title ?? '').toLowerCase() === want);
|
|
244
|
-
if (refs.length > 0) {
|
|
245
|
-
const issues = await client.findAll(tracker_1.default.class.Issue, { _id: { $in: refs.map((r) => r.attachedTo) } });
|
|
246
|
-
for (const issue of issues.filter(open)) {
|
|
247
|
-
const ref = refs.find((r) => r.attachedTo === issue._id);
|
|
248
|
-
found.set(issue._id, { issue, trigger: 'label', since: ref?.createdOn ?? ref?.modifiedOn ?? 0 });
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
if (opts.assigned) {
|
|
253
|
-
const me = await (0, people_1.currentPerson)(client);
|
|
254
|
-
const issues = await client.findAll(tracker_1.default.class.Issue, { assignee: me._id });
|
|
255
|
-
for (const issue of issues.filter(open))
|
|
256
|
-
if (!found.has(issue._id))
|
|
257
|
-
found.set(issue._id, { issue, trigger: 'assigned', since: 0 });
|
|
258
|
-
}
|
|
259
|
-
return [...found.values()]
|
|
260
|
-
.filter((c) => { const prev = state[c.issue._id]; return prev == null || (c.trigger === 'label' && c.since > prev.ranAt); })
|
|
261
|
-
.sort((a, b) => (a.issue.createdOn ?? 0) - (b.issue.createdOn ?? 0));
|
|
262
|
-
}
|
|
263
|
-
/** MCP config for the child Claude: this server, same credentials (inherited env), one workspace. */
|
|
264
|
-
function writeMcpConfig(dir, entry, env) {
|
|
265
|
-
const path = (0, node_path_1.join)(dir, 'mcp.json');
|
|
266
|
-
(0, node_fs_1.writeFileSync)(path, JSON.stringify({ mcpServers: { huly: { command: process.execPath, args: [entry], env } } }, null, 2), { mode: 0o600 });
|
|
267
|
-
return path;
|
|
268
|
-
}
|
|
269
|
-
async function processIssue(c, opts, deps) {
|
|
270
|
-
const { issue } = c;
|
|
271
|
-
const id = issue.identifier;
|
|
272
|
-
const ws = deps.workspace;
|
|
273
|
-
try {
|
|
274
|
-
await (0, agent_1.claimIssue)({ workspace: ws, identifier: id, agent: opts.agent, minutes: opts.timeoutMin + 5, force: false });
|
|
275
|
-
}
|
|
276
|
-
catch (e) {
|
|
277
|
-
deps.log(`skip ${id}: ${e.message.replace(/^Huly MCP: /, '')}`);
|
|
278
|
-
return undefined;
|
|
279
|
-
}
|
|
280
|
-
const childEnv = {
|
|
281
|
-
...deps.env,
|
|
282
|
-
HULY_WORKSPACE: ws,
|
|
283
|
-
HULY_AGENT_NAME: opts.agent,
|
|
284
|
-
HULY_CONFIRM: deps.env.HULY_CONFIRM ?? 'strict',
|
|
285
|
-
HULY_ISSUE: id,
|
|
286
|
-
HULY_ISSUE_TITLE: String(issue.title ?? '')
|
|
287
|
-
};
|
|
288
|
-
const vars = { issue: id, title: String(issue.title ?? ''), workspace: ws, agent: opts.agent, trigger: c.trigger === 'label' ? `label "${opts.label ?? ''}"` : 'assigned to you' };
|
|
289
|
-
vars.prompt = fill(opts.prompt, vars);
|
|
290
|
-
let tmp;
|
|
291
|
-
let code;
|
|
292
|
-
try {
|
|
293
|
-
if (opts.command.includes('{mcpConfig}')) {
|
|
294
|
-
tmp = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'huly-watch-'));
|
|
295
|
-
const pass = {};
|
|
296
|
-
for (const k of ['HULY_WORKSPACE', 'HULY_AGENT_NAME', 'HULY_CONFIRM', 'HULY_TOOLSETS', 'HULY_WRITE_PROJECTS', 'HULY_AUDIT_LOG'])
|
|
297
|
-
if (childEnv[k] != null)
|
|
298
|
-
pass[k] = childEnv[k];
|
|
299
|
-
vars.mcpConfig = writeMcpConfig(tmp, opts.serverEntry ?? process.argv[1], pass);
|
|
300
|
-
}
|
|
301
|
-
const argv = splitCommand(opts.command).map((w) => fill(w, vars));
|
|
302
|
-
deps.log(`run ${id} (${c.trigger}): ${argv[0]} …`);
|
|
303
|
-
code = await deps.exec(argv, opts.cwd, childEnv, opts.timeoutMin * 60_000);
|
|
304
|
-
}
|
|
305
|
-
catch (e) {
|
|
306
|
-
deps.log(`run ${id} failed to start: ${e.message}`);
|
|
307
|
-
code = -1;
|
|
308
|
-
}
|
|
309
|
-
finally {
|
|
310
|
-
if (tmp != null)
|
|
311
|
-
(0, node_fs_1.rmSync)(tmp, { recursive: true, force: true });
|
|
312
|
-
}
|
|
313
|
-
const result = code === 0 ? 'ok' : code == null ? `timeout after ${opts.timeoutMin} min` : `exit ${code}`;
|
|
314
|
-
if (code !== 0) {
|
|
315
|
-
await (0, comments_1.addComment)({ workspace: ws, identifier: id, message: `🤖 Agent run by **${opts.agent}** ended: ${result}. The issue is free again.` });
|
|
316
|
-
}
|
|
317
|
-
// finish_work releases the claim; release it here when the run did not.
|
|
318
|
-
const labels = await deps.client.findAll('tags:class:TagReference', { attachedTo: issue._id });
|
|
319
|
-
if (labels.some((l) => l.title === agent_1.CLAIM_LABEL))
|
|
320
|
-
await (0, agent_1.releaseIssue)({ workspace: ws, identifier: id, agent: opts.agent });
|
|
321
|
-
deps.log(`done ${id}: ${result}`);
|
|
322
|
-
return { identifier: id, trigger: c.trigger, ranAt: (deps.now ?? Date.now)(), result };
|
|
323
|
-
}
|
|
324
|
-
/** One poll: find candidates and run them one after another. */
|
|
325
|
-
async function watchOnce(opts, deps, state, save) {
|
|
326
|
-
const candidates = await findCandidates(deps.client, opts, state);
|
|
327
|
-
if (opts.dryRun) {
|
|
328
|
-
for (const c of candidates)
|
|
329
|
-
deps.log(`would run ${c.issue.identifier} (${c.trigger}): ${c.issue.title}`);
|
|
330
|
-
if (candidates.length === 0)
|
|
331
|
-
deps.log('nothing to do');
|
|
332
|
-
return candidates.length;
|
|
333
|
-
}
|
|
334
|
-
for (const c of candidates) {
|
|
335
|
-
const record = await processIssue(c, opts, deps);
|
|
336
|
-
if (record != null) {
|
|
337
|
-
state[c.issue._id] = record;
|
|
338
|
-
save(state);
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
return candidates.length;
|
|
342
|
-
}
|
|
343
|
-
function execChild(argv, cwd, env, timeoutMs) {
|
|
344
|
-
return new Promise((resolvePromise, reject) => {
|
|
345
|
-
const child = (0, node_child_process_1.spawn)(argv[0], argv.slice(1), { cwd, env, stdio: ['ignore', 'inherit', 'inherit'] });
|
|
346
|
-
let killed = false;
|
|
347
|
-
const timer = setTimeout(() => { killed = true; child.kill('SIGTERM'); }, timeoutMs);
|
|
348
|
-
child.on('error', (e) => { clearTimeout(timer); reject(e); });
|
|
349
|
-
child.on('exit', (code) => { clearTimeout(timer); resolvePromise(killed ? null : code); });
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
async function runWatch(argv) {
|
|
353
|
-
if (argv.includes('--help') || argv.includes('-h')) {
|
|
354
|
-
process.stdout.write(exports.WATCH_HELP);
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
|
-
const opts = parseWatchArgs(argv);
|
|
358
|
-
if (opts.envFile != null) {
|
|
359
|
-
const vars = parseEnvFile((0, node_fs_1.readFileSync)(opts.envFile, 'utf8'));
|
|
360
|
-
for (const [k, v] of Object.entries(vars))
|
|
361
|
-
process.env[k] = v;
|
|
362
|
-
}
|
|
363
|
-
(0, env_1.normalizeEnv)();
|
|
364
|
-
const allowed = (0, guard_1.parseWriteProjects)(process.env.HULY_WRITE_PROJECTS);
|
|
365
|
-
if (allowed != null) {
|
|
366
|
-
const outside = opts.projects.filter((p) => !allowed.has(p));
|
|
367
|
-
if (outside.length > 0)
|
|
368
|
-
throw new Error(`--project ${outside.join(', ')} is outside HULY_WRITE_PROJECTS (${[...allowed].join(', ')}).`);
|
|
369
|
-
if (opts.projects.length === 0)
|
|
370
|
-
opts.projects = [...allowed];
|
|
371
|
-
}
|
|
372
|
-
const conn = await (0, connection_1.getWorkspace)(opts.workspace);
|
|
373
|
-
const ws = conn.workspace.url;
|
|
374
|
-
const me = await (0, people_1.currentPerson)(conn.client);
|
|
375
|
-
const statePath = opts.statePath ?? (0, node_path_1.join)((0, node_os_1.homedir)(), '.huly-mcp', `watch-${ws}.json`);
|
|
376
|
-
const state = loadState(statePath);
|
|
377
|
-
const log = (line) => { process.stderr.write(`[${new Date().toISOString()}] ${line}\n`); };
|
|
378
|
-
const triggers = [opts.label != null ? `label "${opts.label}"` : undefined, opts.assigned ? `assigned to ${me.name}` : undefined].filter((t) => t != null).join(' or ');
|
|
379
|
-
log(`watching ${ws}${opts.projects.length > 0 ? ` (${opts.projects.join(', ')})` : ''} as ${me.name}, agent "${opts.agent}": ${triggers}${opts.dryRun ? ' — dry run' : ''}`);
|
|
380
|
-
let stop = false;
|
|
381
|
-
const onSignal = () => { stop = true; log('stopping after the current run…'); };
|
|
382
|
-
process.on('SIGINT', onSignal);
|
|
383
|
-
process.on('SIGTERM', onSignal);
|
|
384
|
-
const deps = { client: conn.client, workspace: ws, exec: execChild, log, env: process.env };
|
|
385
|
-
try {
|
|
386
|
-
while (!stop) {
|
|
387
|
-
try {
|
|
388
|
-
await watchOnce(opts, deps, state, (s) => saveState(statePath, s));
|
|
389
|
-
}
|
|
390
|
-
catch (e) {
|
|
391
|
-
log(`poll failed: ${e.message}`);
|
|
392
|
-
if (opts.once || opts.dryRun)
|
|
393
|
-
process.exitCode = 1;
|
|
394
|
-
}
|
|
395
|
-
if (opts.once || opts.dryRun)
|
|
396
|
-
break;
|
|
397
|
-
for (let waited = 0; waited < opts.intervalSec * 1000 && !stop; waited += 500)
|
|
398
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
finally {
|
|
402
|
-
await (0, connection_1.closeConnection)();
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
//# sourceMappingURL=watch.js.map
|
package/dist/watch.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Delete a range of issues from a Huly project.
|
|
4
|
-
*
|
|
5
|
-
* Usage:
|
|
6
|
-
* node scripts/cleanup-issues.js <project> <start> <end> [--confirm]
|
|
7
|
-
*
|
|
8
|
-
* Example (dry run — shows what would be deleted):
|
|
9
|
-
* node scripts/cleanup-issues.js VISIO 59 68 --workspace=myteam
|
|
10
|
-
*
|
|
11
|
-
* Example (actually delete):
|
|
12
|
-
* node scripts/cleanup-issues.js VISIO 59 68 --workspace=myteam --confirm
|
|
13
|
-
*
|
|
14
|
-
* Auth is read from .env (HULY_TOKEN, or HULY_EMAIL + HULY_PASSWORD). The target
|
|
15
|
-
* workspace is required: --workspace=<slug> (or HULY_WORKSPACE).
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
'use strict'
|
|
19
|
-
|
|
20
|
-
const fs = require('fs')
|
|
21
|
-
const path = require('path')
|
|
22
|
-
|
|
23
|
-
// Load .env
|
|
24
|
-
const envPath = path.join(__dirname, '..', '.env')
|
|
25
|
-
if (fs.existsSync(envPath)) {
|
|
26
|
-
for (const line of fs.readFileSync(envPath, 'utf8').split('\n')) {
|
|
27
|
-
const m = line.match(/^([^#=\s]+)\s*=\s*(.*)$/)
|
|
28
|
-
if (m) process.env[m[1]] = m[2].trim()
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Target workspace (these scripts write data, so it must be explicit):
|
|
33
|
-
// --workspace=<slug|name|id>, or HULY_WORKSPACE as a fallback.
|
|
34
|
-
const workspace = process.argv.find(a => a.startsWith('--workspace='))?.slice('--workspace='.length) || process.env.HULY_WORKSPACE
|
|
35
|
-
if (!workspace) {
|
|
36
|
-
console.error('❌ No workspace given. Pass --workspace=<slug> (see list_workspaces / npm run setup).')
|
|
37
|
-
process.exit(1)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Load compiled modules
|
|
41
|
-
const distDir = path.join(__dirname, '..', 'dist')
|
|
42
|
-
if (!fs.existsSync(path.join(distDir, 'connection.js'))) {
|
|
43
|
-
console.error('❌ dist/ not found. Run `npm run build` first.')
|
|
44
|
-
process.exit(1)
|
|
45
|
-
}
|
|
46
|
-
const { getConnection, closeConnection } = require(path.join(distDir, 'connection'))
|
|
47
|
-
const tracker = require('@hcengineering/tracker')
|
|
48
|
-
|
|
49
|
-
// Parse args
|
|
50
|
-
const args = process.argv.slice(2)
|
|
51
|
-
const confirm = args.includes('--confirm')
|
|
52
|
-
const positional = args.filter(a => !a.startsWith('--'))
|
|
53
|
-
|
|
54
|
-
const [projectIdentifier, startStr, endStr] = positional
|
|
55
|
-
if (!projectIdentifier || !startStr || !endStr) {
|
|
56
|
-
console.error('Usage: node scripts/cleanup-issues.js <project> <start> <end> --workspace=<slug> [--confirm]')
|
|
57
|
-
console.error('Example: node scripts/cleanup-issues.js VISIO 59 68 --workspace=myteam --confirm')
|
|
58
|
-
process.exit(1)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const start = parseInt(startStr, 10)
|
|
62
|
-
const end = parseInt(endStr, 10)
|
|
63
|
-
if (isNaN(start) || isNaN(end) || start > end) {
|
|
64
|
-
console.error('❌ start and end must be valid numbers with start <= end')
|
|
65
|
-
process.exit(1)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async function main () {
|
|
69
|
-
const identifiers = []
|
|
70
|
-
for (let n = start; n <= end; n++) {
|
|
71
|
-
identifiers.push(`${projectIdentifier}-${n}`)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
console.log(`\n🔍 Huly Issue Cleanup`)
|
|
75
|
-
console.log(` Project: ${projectIdentifier}`)
|
|
76
|
-
console.log(` Range: ${projectIdentifier}-${start} → ${projectIdentifier}-${end} (${identifiers.length} issues)`)
|
|
77
|
-
console.log(` Mode: ${confirm ? '⚠️ DELETING for real' : '👁 DRY RUN (pass --confirm to delete)'}\n`)
|
|
78
|
-
|
|
79
|
-
console.log('🔌 Connecting to Huly...')
|
|
80
|
-
const client = await getConnection(workspace)
|
|
81
|
-
console.log('✅ Connected.\n')
|
|
82
|
-
|
|
83
|
-
// Find all issues in the range
|
|
84
|
-
const issues = await client.findAll(
|
|
85
|
-
tracker.default.class.Issue,
|
|
86
|
-
{ identifier: { $in: identifiers } }
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
if (issues.length === 0) {
|
|
90
|
-
console.log('✅ No matching issues found — nothing to delete.')
|
|
91
|
-
await closeConnection()
|
|
92
|
-
return
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
console.log(`Found ${issues.length} issue(s) to delete:\n`)
|
|
96
|
-
for (const issue of issues) {
|
|
97
|
-
console.log(` • ${issue.identifier} "${issue.title}"`)
|
|
98
|
-
}
|
|
99
|
-
console.log()
|
|
100
|
-
|
|
101
|
-
if (!confirm) {
|
|
102
|
-
console.log('ℹ️ This was a DRY RUN. To actually delete, run:')
|
|
103
|
-
console.log(` node scripts/cleanup-issues.js ${projectIdentifier} ${start} ${end} --confirm\n`)
|
|
104
|
-
await closeConnection()
|
|
105
|
-
return
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Delete
|
|
109
|
-
let deleted = 0
|
|
110
|
-
let failed = 0
|
|
111
|
-
|
|
112
|
-
for (const issue of issues) {
|
|
113
|
-
process.stdout.write(` Deleting ${issue.identifier}... `)
|
|
114
|
-
try {
|
|
115
|
-
await client.removeCollection(
|
|
116
|
-
tracker.default.class.Issue,
|
|
117
|
-
issue.space,
|
|
118
|
-
issue._id,
|
|
119
|
-
issue.attachedTo,
|
|
120
|
-
issue.attachedToClass,
|
|
121
|
-
issue.collection
|
|
122
|
-
)
|
|
123
|
-
console.log('✅')
|
|
124
|
-
deleted++
|
|
125
|
-
} catch (err) {
|
|
126
|
-
console.log(`❌ ${err.message}`)
|
|
127
|
-
failed++
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
await closeConnection()
|
|
132
|
-
|
|
133
|
-
console.log(`\n${'─'.repeat(50)}`)
|
|
134
|
-
console.log(`✅ Deleted: ${deleted} ❌ Failed: ${failed}`)
|
|
135
|
-
console.log(`${'─'.repeat(50)}\n`)
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
main().catch(err => {
|
|
139
|
-
console.error('\n❌ Fatal error:', err.message)
|
|
140
|
-
process.exit(1)
|
|
141
|
-
})
|
package/scripts/copy-guides.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Build step: the plugin skill files are the one source for the agent guides. They are copied to
|
|
3
|
-
// dist/guides/ (without the skill frontmatter) so every MCP client can read them as huly://guide/*.
|
|
4
|
-
'use strict'
|
|
5
|
-
const fs = require('fs')
|
|
6
|
-
const path = require('path')
|
|
7
|
-
|
|
8
|
-
const root = path.join(__dirname, '..')
|
|
9
|
-
const src = path.join(root, 'plugin', 'skills', 'huly')
|
|
10
|
-
const out = path.join(root, 'dist', 'guides')
|
|
11
|
-
const GUIDES = { workflow: 'SKILL.md', costs: 'costs.md', onboarding: 'onboarding.md', features: 'features.md' }
|
|
12
|
-
|
|
13
|
-
fs.mkdirSync(out, { recursive: true })
|
|
14
|
-
for (const [name, file] of Object.entries(GUIDES)) {
|
|
15
|
-
const text = fs.readFileSync(path.join(src, file), 'utf8').replace(/\r\n/g, '\n').replace(/^---\n[\s\S]*?\n---\n+/, '')
|
|
16
|
-
fs.writeFileSync(path.join(out, `${name}.md`), text)
|
|
17
|
-
}
|
|
18
|
-
console.log(`guides: ${Object.keys(GUIDES).length} copied to dist/guides`)
|