@neturely/okffs 0.4.0 → 0.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/CHANGELOG.md +13 -1
- package/README.md +104 -250
- package/dist/board.d.ts +33 -0
- package/dist/board.d.ts.map +1 -0
- package/dist/board.js +171 -0
- package/dist/board.js.map +1 -0
- package/dist/index.js +19 -4
- package/dist/index.js.map +1 -1
- package/dist/projects.d.ts.map +1 -1
- package/dist/projects.js +30 -12
- package/dist/projects.js.map +1 -1
- package/dist/tools/create_issue.d.ts +5 -4
- package/dist/tools/create_issue.d.ts.map +1 -1
- package/dist/tools/create_issue.js +53 -114
- package/dist/tools/create_issue.js.map +1 -1
- package/dist/tools/create_issues_from_list.d.ts +11 -1
- package/dist/tools/create_issues_from_list.d.ts.map +1 -1
- package/dist/tools/create_issues_from_list.js +39 -2
- package/dist/tools/create_issues_from_list.js.map +1 -1
- package/dist/tools/plan.d.ts +11 -1
- package/dist/tools/plan.d.ts.map +1 -1
- package/dist/tools/plan.js +47 -5
- package/dist/tools/plan.js.map +1 -1
- package/package.json +1 -1
package/dist/board.js
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// Shared GitHub Projects v2 board placement for issue-creating tools
|
|
2
|
+
// (create_issue, create_issues_from_list, plan). Centralises: adding an issue to
|
|
3
|
+
// the board, setting Priority/Effort (project-native single-select OR org-level
|
|
4
|
+
// Issue Field — #91), applying the initial Status, and rendering the outcome.
|
|
5
|
+
//
|
|
6
|
+
// Every skip/failure is returned as data and surfaced in the tool response, never
|
|
7
|
+
// only console.warn'd to stderr (which the host/user never sees) — #146. The add
|
|
8
|
+
// itself throwing is the one fatal-to-board case; callers catch it into
|
|
9
|
+
// `boardError`. Field writes are always non-fatal.
|
|
10
|
+
import { config } from "./config.js";
|
|
11
|
+
import { addIssueToProject, getProjectMetadata, setProjectFieldValue, getOrgIssueField, setIssueFieldSingleSelect, } from "./projects.js";
|
|
12
|
+
// Whether create_* tools should attempt board auto-add at all.
|
|
13
|
+
export function boardAutoAddEnabled() {
|
|
14
|
+
return Boolean(config.projectAutoAdd && config.projectEnabled);
|
|
15
|
+
}
|
|
16
|
+
// The board's real option names for a single-select field (e.g. "Priority") —
|
|
17
|
+
// project-native options if present, otherwise the org-level Issue Field options
|
|
18
|
+
// (only readable with a classic PAT). Returns null when the board is unreachable,
|
|
19
|
+
// the field is absent, or its options can't be read — callers then fall back to a
|
|
20
|
+
// generic scale. Cheap after the first call (metadata + org field are memoized).
|
|
21
|
+
// Used to inject real options into create_issue's inference guidance (#133).
|
|
22
|
+
export async function getBoardFieldOptions(label) {
|
|
23
|
+
try {
|
|
24
|
+
const meta = await getProjectMetadata();
|
|
25
|
+
const native = meta.singleSelectByName.get(label.toLowerCase());
|
|
26
|
+
if (native && native.options.size > 0)
|
|
27
|
+
return [...native.options.keys()];
|
|
28
|
+
// No project-native options → it's an org-level Issue Field, readable only
|
|
29
|
+
// with a classic admin:org PAT (#91). Skip otherwise.
|
|
30
|
+
if (config.classicPat) {
|
|
31
|
+
const orgField = await getOrgIssueField(label);
|
|
32
|
+
if (orgField && orgField.options.size > 0)
|
|
33
|
+
return [...orgField.options.keys()];
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Set a board single-select field (Priority, Effort, …) to `value`. Handles both
|
|
42
|
+
// shapes: a project-native single-select (set on the project item), and a GitHub
|
|
43
|
+
// org-level Issue Field (project field reports no options → set on the issue via
|
|
44
|
+
// setIssueFieldSingleSelect, gated on OKFFS_CLASSIC_PAT — #91). Returns
|
|
45
|
+
// { skipped: reason } on any miss and { applied } on success; also warns to
|
|
46
|
+
// stderr for server logs, but the returned reason is what the caller surfaces.
|
|
47
|
+
async function applyBoardSingleSelect(label, value, itemId, issueNodeId, meta) {
|
|
48
|
+
const skip = (reason) => {
|
|
49
|
+
console.warn(`[okffs] ${label} "${value}" not set: ${reason}`);
|
|
50
|
+
return { skipped: reason };
|
|
51
|
+
};
|
|
52
|
+
const native = meta.singleSelectByName.get(label.toLowerCase());
|
|
53
|
+
if (!native) {
|
|
54
|
+
return skip(`the board has no ${label} field.`);
|
|
55
|
+
}
|
|
56
|
+
// Project-native single-select with resolvable options.
|
|
57
|
+
if (native.options.size > 0) {
|
|
58
|
+
const optionId = native.options.get(value);
|
|
59
|
+
if (!optionId) {
|
|
60
|
+
return skip(`no matching option. Board ${label} options: ${[...native.options.keys()].join(", ")}.`);
|
|
61
|
+
}
|
|
62
|
+
// Catch write failures here too — addIssueToBoard's contract is that field
|
|
63
|
+
// writes never throw, so a failed set must degrade to a surfaced skip rather
|
|
64
|
+
// than turning a successful board add into a full boardError.
|
|
65
|
+
try {
|
|
66
|
+
await setProjectFieldValue(itemId, native.fieldId, optionId);
|
|
67
|
+
return { applied: value };
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
return skip(`write failed — ${err instanceof Error ? err.message : String(err)}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// No options via the project API → it's a GitHub org-level Issue Field.
|
|
74
|
+
if (!config.classicPat) {
|
|
75
|
+
return skip(`the board's ${label} is an org-level Issue Field, which okffs can only set with a classic ` +
|
|
76
|
+
`PAT (\`admin:org\`) and OKFFS_CLASSIC_PAT=true (security tradeoff — see docs). Set it in the board UI for now.`);
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
const orgField = await getOrgIssueField(label);
|
|
80
|
+
if (!orgField) {
|
|
81
|
+
return skip(`no org-level ${label} Issue Field found.`);
|
|
82
|
+
}
|
|
83
|
+
const orgOptionId = orgField.options.get(value);
|
|
84
|
+
if (!orgOptionId) {
|
|
85
|
+
return skip(`no matching org Issue Field option. Options: ${[...orgField.options.keys()].join(", ")}.`);
|
|
86
|
+
}
|
|
87
|
+
await setIssueFieldSingleSelect(issueNodeId, orgField.fieldId, orgOptionId);
|
|
88
|
+
return { applied: value };
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
// Permission (fine-grained PAT FORBIDDEN) / preview-API errors — never fatal.
|
|
92
|
+
return skip(`org Issue Field write failed — ${err instanceof Error ? err.message : String(err)}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Add an issue to the configured board and set Priority/Effort. Throws if the add
|
|
96
|
+
// itself fails (caller catches into boardError). Field writes never throw. Does
|
|
97
|
+
// NOT set the initial Status — that must run after any draft PR (see
|
|
98
|
+
// applyInitialStatus) so it wins GitHub's linked-PR "In Progress" promotion (#103).
|
|
99
|
+
export async function addIssueToBoard(issueNodeId, opts) {
|
|
100
|
+
const itemId = await addIssueToProject(issueNodeId);
|
|
101
|
+
let priority = null;
|
|
102
|
+
let effort = null;
|
|
103
|
+
if (opts.priority || opts.effort) {
|
|
104
|
+
const meta = await getProjectMetadata();
|
|
105
|
+
if (opts.priority) {
|
|
106
|
+
priority = await applyBoardSingleSelect("Priority", opts.priority, itemId, issueNodeId, meta);
|
|
107
|
+
}
|
|
108
|
+
if (opts.effort) {
|
|
109
|
+
effort = await applyBoardSingleSelect("Effort", opts.effort, itemId, issueNodeId, meta);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return { itemId, priority, effort };
|
|
113
|
+
}
|
|
114
|
+
// Pin the board Status to OKFFS_PROJECT_INITIAL_STATUS for a freshly-added item.
|
|
115
|
+
// No-op (returns nulls) when the env var is unset. Non-fatal: any miss is returned
|
|
116
|
+
// as `skipped` and warned to stderr. Call AFTER the draft PR so it wins the race
|
|
117
|
+
// with GitHub's linked-PR automation (#103).
|
|
118
|
+
export async function applyInitialStatus(itemId) {
|
|
119
|
+
if (!config.projectInitialStatus)
|
|
120
|
+
return { applied: null, skipped: null };
|
|
121
|
+
const wanted = config.projectInitialStatus;
|
|
122
|
+
try {
|
|
123
|
+
const meta = await getProjectMetadata();
|
|
124
|
+
const optionId = meta.statusFieldId ? meta.statusOptions.get(wanted) : undefined;
|
|
125
|
+
if (meta.statusFieldId && optionId) {
|
|
126
|
+
await setProjectFieldValue(itemId, meta.statusFieldId, optionId);
|
|
127
|
+
return { applied: wanted, skipped: null };
|
|
128
|
+
}
|
|
129
|
+
const skipped = !meta.statusFieldId
|
|
130
|
+
? "the board has no Status field."
|
|
131
|
+
: `no matching Status option. Board Status options: ${[...meta.statusOptions.keys()].join(", ")}.`;
|
|
132
|
+
console.warn(`[okffs] initial status "${wanted}" not set: ${skipped}`);
|
|
133
|
+
return { applied: null, skipped };
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
const skipped = `Status write failed — ${err instanceof Error ? err.message : String(err)}`;
|
|
137
|
+
console.warn(`[okffs] initial status "${wanted}" not set: ${skipped}`);
|
|
138
|
+
return { applied: null, skipped };
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Render board outcome lines for a tool response — shared by all three creators so
|
|
142
|
+
// applied fields and every skip read identically. `indent` prefixes each line
|
|
143
|
+
// (batch tools nest board lines under their per-issue entry).
|
|
144
|
+
export function renderBoardLines(args) {
|
|
145
|
+
const ind = args.indent ?? "";
|
|
146
|
+
const lines = [];
|
|
147
|
+
if (args.addedToBoard) {
|
|
148
|
+
const bits = [
|
|
149
|
+
args.priority && "applied" in args.priority ? `priority: ${args.priority.applied}` : null,
|
|
150
|
+
args.effort && "applied" in args.effort ? `effort: ${args.effort.applied}` : null,
|
|
151
|
+
args.initialStatus?.applied ? `status: ${args.initialStatus.applied}` : null,
|
|
152
|
+
].filter(Boolean);
|
|
153
|
+
lines.push(`${ind}Board: added to the project${bits.length ? ` (${bits.join(", ")})` : ""}`);
|
|
154
|
+
// Surface any requested-but-not-applied field so an enabled board step is
|
|
155
|
+
// never silently dropped (the issue is still created fine) — see #146.
|
|
156
|
+
const skips = [
|
|
157
|
+
args.priority && "skipped" in args.priority ? `Priority "${args.requestedPriority}" not set — ${args.priority.skipped}` : null,
|
|
158
|
+
args.effort && "skipped" in args.effort ? `Effort "${args.requestedEffort}" not set — ${args.effort.skipped}` : null,
|
|
159
|
+
args.initialStatus?.skipped ? `Initial status "${args.requestedStatus}" not set — ${args.initialStatus.skipped}` : null,
|
|
160
|
+
].filter(Boolean);
|
|
161
|
+
for (const s of skips)
|
|
162
|
+
lines.push(`${ind} ⚠ ${s}`);
|
|
163
|
+
}
|
|
164
|
+
else if (args.boardError) {
|
|
165
|
+
// Auto-add was enabled but the add itself failed. Surface it (not just the
|
|
166
|
+
// server log) so an empty board doesn't look like success — see #101.
|
|
167
|
+
lines.push(`${ind}Board: NOT added — auto-add is on but failed. The issue itself was created fine.`, `${ind} ${args.boardError}`);
|
|
168
|
+
}
|
|
169
|
+
return lines;
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=board.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"board.js","sourceRoot":"","sources":["../src/board.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -31,10 +31,25 @@ const prompts = [addressPrReview, updateGuidance];
|
|
|
31
31
|
const version = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
32
32
|
const server = new Server({ name: "okffs", version }, { capabilities: { tools: {}, prompts: {} } });
|
|
33
33
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
// A tool may export an async getDescription() to compute its description at
|
|
35
|
+
// list time (e.g. create_issue injects the board's real Priority/Effort options
|
|
36
|
+
// — #133). Fall back to the static description on absence or failure.
|
|
37
|
+
tools: await Promise.all(tools.map(async (t) => {
|
|
38
|
+
let description = t.description;
|
|
39
|
+
const getDescription = t.getDescription;
|
|
40
|
+
if (getDescription) {
|
|
41
|
+
try {
|
|
42
|
+
description = await getDescription();
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
console.warn(`[okffs] getDescription() failed for ${t.name}, using static description:`, err instanceof Error ? err.message : err);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
name: t.name,
|
|
50
|
+
description,
|
|
51
|
+
inputSchema: zodToJsonSchema(t.inputSchema),
|
|
52
|
+
};
|
|
38
53
|
})),
|
|
39
54
|
}));
|
|
40
55
|
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,YAAY,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAC;AACjD,OAAO,KAAK,YAAY,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,oBAAoB,MAAM,oCAAoC,CAAC;AAC3E,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AACxC,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,iBAAiB,MAAM,gCAAgC,CAAC;AACpE,OAAO,KAAK,eAAe,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,oBAAoB,MAAM,oCAAoC,CAAC;AAC3E,OAAO,KAAK,oBAAoB,MAAM,oCAAoC,CAAC;AAC3E,OAAO,KAAK,mBAAmB,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,cAAc,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,mBAAmB,MAAM,kCAAkC,CAAC;AAExE,OAAO,KAAK,eAAe,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,cAAc,MAAM,8BAA8B,CAAC;AAE/D,MAAM,KAAK,GAAG,CAAC,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,oBAAoB,EAAE,IAAI,EAAE,UAAU,EAAE,iBAAiB,EAAE,eAAe,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,cAAc,EAAE,mBAAmB,CAAC,CAAC;AAEzR,MAAM,OAAO,GAAG,CAAC,eAAe,EAAE,cAAc,CAAC,CAAC;AAElD,iFAAiF;AACjF,6EAA6E;AAC7E,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CACxB,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAClE,CAAC,OAAO,CAAC;AAEV,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,EAC1B,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,CAC7C,CAAC;AAEF,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;IAC5D,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/projects.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../src/projects.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAM9B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;CACtD;AA0CD,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,eAAe,CAAC,CAQ7D;AA8DD,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW5E;AAGD,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAaf;
|
|
1
|
+
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../src/projects.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAM9B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;CACtD;AA0CD,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,eAAe,CAAC,CAQ7D;AA8DD,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW5E;AAGD,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAaf;AAqDD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAUD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAW5E;AA8CD,wBAAsB,yBAAyB,CAC7C,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAYf;AAGD,wBAAsB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAsBxF;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAKD,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAkD7F;AASD,wBAAsB,8BAA8B,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAkDhG"}
|
package/dist/projects.js
CHANGED
|
@@ -117,21 +117,39 @@ export async function setProjectFieldValue(itemId, fieldId, optionId) {
|
|
|
117
117
|
// `admin:org` scope works; fine-grained PATs currently get FORBIDDEN for this
|
|
118
118
|
// preview API. Translate that into an actionable message rather than the
|
|
119
119
|
// Projects-scope one.
|
|
120
|
+
// The org-level Issue Fields API is a GitHub preview and is noticeably flaky —
|
|
121
|
+
// transient 5xx / timeouts / secondary-rate blips are common. Retry those a
|
|
122
|
+
// couple of times with a short backoff (#137). Permission errors (403/FORBIDDEN)
|
|
123
|
+
// are deterministic, so they are translated and thrown immediately, never retried.
|
|
124
|
+
const ORG_FIELD_MAX_ATTEMPTS = 3;
|
|
125
|
+
const ORG_FIELD_RETRY_BASE_MS = 300;
|
|
126
|
+
function isOrgFieldPermissionError(msg) {
|
|
127
|
+
return /\b403\b|FORBIDDEN|not accessible/i.test(msg);
|
|
128
|
+
}
|
|
120
129
|
async function orgFieldCall(fn) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
"
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
let lastErr;
|
|
131
|
+
for (let attempt = 1; attempt <= ORG_FIELD_MAX_ATTEMPTS; attempt++) {
|
|
132
|
+
try {
|
|
133
|
+
return await fn();
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
137
|
+
if (isOrgFieldPermissionError(msg)) {
|
|
138
|
+
throw new Error("[okffs] GitHub denied access to org-level Issue Fields (organization.issueFields). " +
|
|
139
|
+
"This is a separate permission from Projects: a classic PAT with the `admin:org` scope works; " +
|
|
140
|
+
"fine-grained PATs currently return FORBIDDEN for this preview API. Use an org-capable GITHUB_TOKEN " +
|
|
141
|
+
"or set the field manually in the board UI. " +
|
|
142
|
+
`Original error: ${msg}`);
|
|
143
|
+
}
|
|
144
|
+
lastErr = err;
|
|
145
|
+
if (attempt < ORG_FIELD_MAX_ATTEMPTS) {
|
|
146
|
+
console.warn(`[okffs] org Issue Fields API call failed (attempt ${attempt}/${ORG_FIELD_MAX_ATTEMPTS}), retrying: ${msg}`);
|
|
147
|
+
await new Promise((resolve) => setTimeout(resolve, ORG_FIELD_RETRY_BASE_MS * attempt));
|
|
148
|
+
}
|
|
132
149
|
}
|
|
133
|
-
throw err;
|
|
134
150
|
}
|
|
151
|
+
// Normalize to an Error so callers' `err instanceof Error` handling is reliable.
|
|
152
|
+
throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));
|
|
135
153
|
}
|
|
136
154
|
// Per-field-name cache so each org Issue Field (Priority, Effort, …) is fetched
|
|
137
155
|
// at most once per process. On failure the entry is cleared so a later call can
|
package/dist/projects.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projects.js","sourceRoot":"","sources":["../src/projects.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"projects.js","sourceRoot":"","sources":["../src/projects.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export declare const name = "create_issue";
|
|
3
3
|
export declare const description: string;
|
|
4
|
+
export declare function getDescription(): Promise<string>;
|
|
4
5
|
export declare const inputSchema: z.ZodObject<{
|
|
5
6
|
title: z.ZodString;
|
|
6
7
|
description: z.ZodString;
|
|
@@ -12,19 +13,19 @@ export declare const inputSchema: z.ZodObject<{
|
|
|
12
13
|
}, "strip", z.ZodTypeAny, {
|
|
13
14
|
title: string;
|
|
14
15
|
description: string;
|
|
16
|
+
priority?: string | undefined;
|
|
17
|
+
effort?: string | undefined;
|
|
15
18
|
assignees?: string[] | undefined;
|
|
16
19
|
labels?: string[] | undefined;
|
|
17
20
|
milestone?: number | undefined;
|
|
18
|
-
priority?: string | undefined;
|
|
19
|
-
effort?: string | undefined;
|
|
20
21
|
}, {
|
|
21
22
|
title: string;
|
|
22
23
|
description: string;
|
|
24
|
+
priority?: string | undefined;
|
|
25
|
+
effort?: string | undefined;
|
|
23
26
|
assignees?: string[] | undefined;
|
|
24
27
|
labels?: string[] | undefined;
|
|
25
28
|
milestone?: number | undefined;
|
|
26
|
-
priority?: string | undefined;
|
|
27
|
-
effort?: string | undefined;
|
|
28
29
|
}>;
|
|
29
30
|
export declare function handler(input: z.infer<typeof inputSchema>): Promise<{
|
|
30
31
|
content: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create_issue.d.ts","sourceRoot":"","sources":["../../src/tools/create_issue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"create_issue.d.ts","sourceRoot":"","sources":["../../src/tools/create_issue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAcxB,eAAO,MAAM,IAAI,iBAAiB,CAAC;AAiCnC,eAAO,MAAM,WAAW,QAA4D,CAAC;AAMrF,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAStD;AAED,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;EAYtB,CAAC;AAEH,wBAAsB,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;GAmJ/D"}
|
|
@@ -2,76 +2,51 @@ import { z } from "zod";
|
|
|
2
2
|
import { createIssue, updateIssueBody, getDefaultBranch, getRef, createBranch, buildBranchName, createDraftPullRequest } from "../github.js";
|
|
3
3
|
import { config } from "../config.js";
|
|
4
4
|
import { git, currentBranch } from "../git.js";
|
|
5
|
-
import {
|
|
6
|
-
// Set a board single-select field (Priority, Effort, …) to `value`. Handles both
|
|
7
|
-
// shapes: a project-native single-select (set on the project item), and a GitHub
|
|
8
|
-
// org-level Issue Field (project field reports no options → set on the issue via
|
|
9
|
-
// setIssueFieldValue, gated on OKFFS_CLASSIC_PAT — #91). Non-fatal: warns and
|
|
10
|
-
// returns null on any miss. Returns the applied value on success.
|
|
11
|
-
async function applyBoardSingleSelect(label, value, itemId, issueNodeId, meta) {
|
|
12
|
-
const native = meta.singleSelectByName.get(label.toLowerCase());
|
|
13
|
-
if (!native) {
|
|
14
|
-
console.warn(`[okffs] ${label} "${value}" not set: the board has no ${label} field.`);
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
// Project-native single-select with resolvable options.
|
|
18
|
-
if (native.options.size > 0) {
|
|
19
|
-
const optionId = native.options.get(value);
|
|
20
|
-
if (optionId) {
|
|
21
|
-
await setProjectFieldValue(itemId, native.fieldId, optionId);
|
|
22
|
-
return value;
|
|
23
|
-
}
|
|
24
|
-
console.warn(`[okffs] ${label} "${value}" not set — no matching option. Board ${label} options: ${[...native.options.keys()].join(", ")}.`);
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
// No options via the project API → it's a GitHub org-level Issue Field.
|
|
28
|
-
if (!config.classicPat) {
|
|
29
|
-
console.warn(`[okffs] ${label} "${value}" not set: the board's ${label} is an org-level Issue Field, ` +
|
|
30
|
-
`which okffs can only set with a classic PAT (\`admin:org\`) and OKFFS_CLASSIC_PAT=true (security tradeoff — see docs). ` +
|
|
31
|
-
`Set it manually in the board UI for now.`);
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
try {
|
|
35
|
-
const orgField = await getOrgIssueField(label);
|
|
36
|
-
if (!orgField) {
|
|
37
|
-
console.warn(`[okffs] ${label} "${value}" not set: no org-level ${label} Issue Field found.`);
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
const orgOptionId = orgField.options.get(value);
|
|
41
|
-
if (!orgOptionId) {
|
|
42
|
-
console.warn(`[okffs] ${label} "${value}" not set — no matching org Issue Field option. Options: ${[...orgField.options.keys()].join(", ")}.`);
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
await setIssueFieldSingleSelect(issueNodeId, orgField.fieldId, orgOptionId);
|
|
46
|
-
return value;
|
|
47
|
-
}
|
|
48
|
-
catch (err) {
|
|
49
|
-
// Permission (fine-grained PAT FORBIDDEN) / preview-API errors — never fatal.
|
|
50
|
-
console.warn(`[okffs] ${label} not set via org Issue Field:`, err instanceof Error ? err.message : err);
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
5
|
+
import { boardAutoAddEnabled, addIssueToBoard, applyInitialStatus, renderBoardLines, getBoardFieldOptions, } from "../board.js";
|
|
54
6
|
export const name = "create_issue";
|
|
7
|
+
const DESCRIPTION_HEAD = "Create a GitHub issue and automatically create a matching branch. Before calling this tool, infer appropriate labels from the issue title and description using GitHub's default labels: bug, documentation, duplicate, enhancement, good first issue, help wanted, invalid, question, wontfix. Pass the inferred labels in the labels parameter unless the user has specified their own.";
|
|
8
|
+
const DESCRIPTION_TAIL = " If the user mentions that this issue is blocked by, blocking, or a child of another issue, call link_issues after creating this issue to set the relationship. Returns the issue URL, issue number, and branch name.";
|
|
55
9
|
// Priority/Effort inference guidance is woven into the tool description so Claude
|
|
56
10
|
// uses its own judgement to triage the issue it's creating (like it already does
|
|
57
11
|
// for labels), falling back to OKFFS_DEFAULT_* only when it can't tell. Toggle per
|
|
58
|
-
// field with OKFFS_INFER_PRIORITY / OKFFS_INFER_EFFORT (default on).
|
|
59
|
-
|
|
12
|
+
// field with OKFFS_INFER_PRIORITY / OKFFS_INFER_EFFORT (default on). When the
|
|
13
|
+
// board's real option names are known they replace the generic scale so Claude
|
|
14
|
+
// infers against the actual options (#133) — e.g. a P0/P1/P2 board.
|
|
15
|
+
function inferenceGuidance(priorityOpts, effortOpts) {
|
|
60
16
|
const bits = [];
|
|
61
17
|
if (config.inferPriority) {
|
|
62
|
-
|
|
18
|
+
const scale = priorityOpts?.length ? priorityOpts.join(", ") : "Urgent, High, Medium, Low";
|
|
19
|
+
bits.push(`infer a \`priority\` for the issue from its urgency and impact (board options: ${scale})`);
|
|
63
20
|
}
|
|
64
21
|
if (config.inferEffort) {
|
|
65
|
-
|
|
22
|
+
const scale = effortOpts?.length ? effortOpts.join(", ") : "High, Medium, Low";
|
|
23
|
+
bits.push(`infer an \`effort\` from the expected amount of work (board options: ${scale})`);
|
|
66
24
|
}
|
|
67
25
|
if (bits.length === 0)
|
|
68
26
|
return "";
|
|
69
27
|
return (` Also ${bits.join(" and ")}, passing the value(s) in the matching parameter. ` +
|
|
70
28
|
"okffs matches these against the board's actual options and falls back to OKFFS_DEFAULT_PRIORITY / OKFFS_DEFAULT_EFFORT when you omit them — so if you genuinely can't judge, omit the field rather than guessing.");
|
|
71
29
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
30
|
+
// Static description (generic scale) — the safe fallback used before the board is
|
|
31
|
+
// reachable and whenever real options can't be read.
|
|
32
|
+
export const description = DESCRIPTION_HEAD + inferenceGuidance() + DESCRIPTION_TAIL;
|
|
33
|
+
// Dynamic description resolved at tools/list time (index.ts awaits this). When
|
|
34
|
+
// auto-add is on and inference is enabled, inject the board's real Priority/Effort
|
|
35
|
+
// option names so Claude infers against them (#133). Any miss falls back to the
|
|
36
|
+
// static description. Cheap after the first call — board metadata is memoized.
|
|
37
|
+
export async function getDescription() {
|
|
38
|
+
if (!boardAutoAddEnabled())
|
|
39
|
+
return description;
|
|
40
|
+
if (!config.inferPriority && !config.inferEffort)
|
|
41
|
+
return description;
|
|
42
|
+
const [priorityOpts, effortOpts] = await Promise.all([
|
|
43
|
+
config.inferPriority ? getBoardFieldOptions("Priority") : Promise.resolve(null),
|
|
44
|
+
config.inferEffort ? getBoardFieldOptions("Effort") : Promise.resolve(null),
|
|
45
|
+
]);
|
|
46
|
+
if (!priorityOpts && !effortOpts)
|
|
47
|
+
return description;
|
|
48
|
+
return DESCRIPTION_HEAD + inferenceGuidance(priorityOpts, effortOpts) + DESCRIPTION_TAIL;
|
|
49
|
+
}
|
|
75
50
|
export const inputSchema = z.object({
|
|
76
51
|
title: z.string().describe("Issue title"),
|
|
77
52
|
description: z.string().describe("Issue body / description"),
|
|
@@ -97,29 +72,15 @@ export async function handler(input) {
|
|
|
97
72
|
const updatedBody = `${input.description}\n\n**Branch:** \`${branchName}\``;
|
|
98
73
|
await updateIssueBody(issue.number, updatedBody);
|
|
99
74
|
// Add the issue to the configured Project board (fallback for users without
|
|
100
|
-
// native board automation). Non-fatal, mirroring the
|
|
101
|
-
// failure warns with an [okffs] prefix
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
let
|
|
75
|
+
// native board automation) and set Priority/Effort. Non-fatal, mirroring the
|
|
76
|
+
// autoPR block below: any failure warns with an [okffs] prefix, is surfaced in
|
|
77
|
+
// the response, and never blocks issue creation. Initial Status is applied
|
|
78
|
+
// later (after the draft PR) — see the applyInitialStatus call below.
|
|
79
|
+
let boardAdd = null;
|
|
105
80
|
let boardError = null;
|
|
106
|
-
|
|
107
|
-
if (config.projectAutoAdd && config.projectEnabled) {
|
|
81
|
+
if (boardAutoAddEnabled()) {
|
|
108
82
|
try {
|
|
109
|
-
|
|
110
|
-
boardItemId = itemId;
|
|
111
|
-
addedToBoard = true;
|
|
112
|
-
// Priority and Effort are set the same way — project-native single-select,
|
|
113
|
-
// or a GitHub org-level Issue Field when OKFFS_CLASSIC_PAT is on (#91).
|
|
114
|
-
if (resolvedPriority || resolvedEffort) {
|
|
115
|
-
const meta = await getProjectMetadata();
|
|
116
|
-
if (resolvedPriority) {
|
|
117
|
-
priorityApplied = await applyBoardSingleSelect("Priority", resolvedPriority, itemId, issue.node_id, meta);
|
|
118
|
-
}
|
|
119
|
-
if (resolvedEffort) {
|
|
120
|
-
effortApplied = await applyBoardSingleSelect("Effort", resolvedEffort, itemId, issue.node_id, meta);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
83
|
+
boardAdd = await addIssueToBoard(issue.node_id, { priority: resolvedPriority, effort: resolvedEffort });
|
|
123
84
|
}
|
|
124
85
|
catch (err) {
|
|
125
86
|
boardError = err instanceof Error ? err.message : String(err);
|
|
@@ -165,28 +126,9 @@ export async function handler(input) {
|
|
|
165
126
|
// issue to "In Progress". Setting our intended status here lets it win that
|
|
166
127
|
// race so freshly-created issues land where okffs means them to (#103).
|
|
167
128
|
// Non-fatal, like the rest of the board handling.
|
|
168
|
-
let
|
|
169
|
-
if (
|
|
170
|
-
|
|
171
|
-
const meta = await getProjectMetadata();
|
|
172
|
-
const optionId = meta.statusFieldId
|
|
173
|
-
? meta.statusOptions.get(config.projectInitialStatus)
|
|
174
|
-
: undefined;
|
|
175
|
-
if (meta.statusFieldId && optionId) {
|
|
176
|
-
await setProjectFieldValue(boardItemId, meta.statusFieldId, optionId);
|
|
177
|
-
initialStatusApplied = config.projectInitialStatus;
|
|
178
|
-
}
|
|
179
|
-
else if (!meta.statusFieldId) {
|
|
180
|
-
console.warn(`[okffs] OKFFS_PROJECT_INITIAL_STATUS set but the board has no Status field.`);
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
const opts = [...meta.statusOptions.keys()].join(", ");
|
|
184
|
-
console.warn(`[okffs] OKFFS_PROJECT_INITIAL_STATUS "${config.projectInitialStatus}" doesn't match a board Status option. Options: ${opts}.`);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
catch (err) {
|
|
188
|
-
console.warn("[okffs] Failed to set initial board status:", err instanceof Error ? err.message : err);
|
|
189
|
-
}
|
|
129
|
+
let initialStatus = null;
|
|
130
|
+
if (boardAdd) {
|
|
131
|
+
initialStatus = await applyInitialStatus(boardAdd.itemId);
|
|
190
132
|
}
|
|
191
133
|
const lines = [
|
|
192
134
|
`Issue #${issue.number} created: ${issue.html_url}`,
|
|
@@ -203,25 +145,22 @@ export async function handler(input) {
|
|
|
203
145
|
const source = input.labels ? "" : " (default)";
|
|
204
146
|
lines.push(`Labels: ${resolvedLabels.join(", ")}${source}`);
|
|
205
147
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
// otherwise makes an empty board look like it worked. See #101.
|
|
218
|
-
lines.push(`Board: NOT added — auto-add is on but failed. The issue itself was created fine.`, ` ${boardError}`);
|
|
219
|
-
}
|
|
148
|
+
const addedToBoard = Boolean(boardAdd);
|
|
149
|
+
lines.push(...renderBoardLines({
|
|
150
|
+
addedToBoard,
|
|
151
|
+
boardError,
|
|
152
|
+
requestedPriority: resolvedPriority,
|
|
153
|
+
priority: boardAdd?.priority ?? null,
|
|
154
|
+
requestedEffort: resolvedEffort,
|
|
155
|
+
effort: boardAdd?.effort ?? null,
|
|
156
|
+
requestedStatus: config.projectInitialStatus,
|
|
157
|
+
initialStatus,
|
|
158
|
+
}));
|
|
220
159
|
lines.push(``, `To start work:`, ` git fetch origin`, ` git checkout ${branchName}`);
|
|
221
160
|
// Conversational nudge: prompt the host LLM to offer moving the issue into
|
|
222
161
|
// the "In Progress" column via update_project_status once work begins.
|
|
223
162
|
if (addedToBoard) {
|
|
224
|
-
const where =
|
|
163
|
+
const where = initialStatus?.applied ? `"${initialStatus.applied}"` : "its default column";
|
|
225
164
|
lines.push(``, `This issue is on the board in ${where}. Want me to move it to "In Progress" and start? ` +
|
|
226
165
|
`(I can call update_project_status for #${issue.number}.)`);
|
|
227
166
|
}
|