@selfagency/beans-mcp 0.4.2 → 0.6.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/README.md +251 -27
- package/beans-mcp-server.cjs +957 -163
- package/index.cjs +959 -163
- package/index.d.ts +154 -2
- package/index.js +959 -164
- package/package.json +10 -9
package/index.cjs
CHANGED
|
@@ -14433,7 +14433,7 @@ var init_v4 = __esm({
|
|
|
14433
14433
|
}
|
|
14434
14434
|
});
|
|
14435
14435
|
|
|
14436
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
14436
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
|
|
14437
14437
|
function assertCompleteRequestPrompt(request) {
|
|
14438
14438
|
if (request.params.ref.type !== "ref/prompt") {
|
|
14439
14439
|
throw new TypeError(`Expected CompleteRequestPrompt, but got ${request.params.ref.type}`);
|
|
@@ -14448,7 +14448,7 @@ function assertCompleteRequestResourceTemplate(request) {
|
|
|
14448
14448
|
}
|
|
14449
14449
|
var LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, RELATED_TASK_META_KEY, JSONRPC_VERSION, AssertObjectSchema, ProgressTokenSchema, CursorSchema, TaskCreationParamsSchema, TaskMetadataSchema, RelatedTaskMetadataSchema, RequestMetaSchema, BaseRequestParamsSchema, TaskAugmentedRequestParamsSchema, isTaskAugmentedRequestParams, RequestSchema, NotificationsParamsSchema, NotificationSchema, ResultSchema, RequestIdSchema, JSONRPCRequestSchema, isJSONRPCRequest, JSONRPCNotificationSchema, isJSONRPCNotification, JSONRPCResultResponseSchema, isJSONRPCResultResponse, ErrorCode, JSONRPCErrorResponseSchema, isJSONRPCErrorResponse, JSONRPCMessageSchema, JSONRPCResponseSchema, EmptyResultSchema, CancelledNotificationParamsSchema, CancelledNotificationSchema, IconSchema, IconsSchema, BaseMetadataSchema, ImplementationSchema, FormElicitationCapabilitySchema, ElicitationCapabilitySchema, ClientTasksCapabilitySchema, ServerTasksCapabilitySchema, ClientCapabilitiesSchema, InitializeRequestParamsSchema, InitializeRequestSchema, ServerCapabilitiesSchema, InitializeResultSchema, InitializedNotificationSchema, PingRequestSchema, ProgressSchema, ProgressNotificationParamsSchema, ProgressNotificationSchema, PaginatedRequestParamsSchema, PaginatedRequestSchema, PaginatedResultSchema, TaskStatusSchema, TaskSchema, CreateTaskResultSchema, TaskStatusNotificationParamsSchema, TaskStatusNotificationSchema, GetTaskRequestSchema, GetTaskResultSchema, GetTaskPayloadRequestSchema, GetTaskPayloadResultSchema, ListTasksRequestSchema, ListTasksResultSchema, CancelTaskRequestSchema, CancelTaskResultSchema, ResourceContentsSchema, TextResourceContentsSchema, Base64Schema, BlobResourceContentsSchema, RoleSchema, AnnotationsSchema, ResourceSchema, ResourceTemplateSchema, ListResourcesRequestSchema, ListResourcesResultSchema, ListResourceTemplatesRequestSchema, ListResourceTemplatesResultSchema, ResourceRequestParamsSchema, ReadResourceRequestParamsSchema, ReadResourceRequestSchema, ReadResourceResultSchema, ResourceListChangedNotificationSchema, SubscribeRequestParamsSchema, SubscribeRequestSchema, UnsubscribeRequestParamsSchema, UnsubscribeRequestSchema, ResourceUpdatedNotificationParamsSchema, ResourceUpdatedNotificationSchema, PromptArgumentSchema, PromptSchema, ListPromptsRequestSchema, ListPromptsResultSchema, GetPromptRequestParamsSchema, GetPromptRequestSchema, TextContentSchema, ImageContentSchema, AudioContentSchema, ToolUseContentSchema, EmbeddedResourceSchema, ResourceLinkSchema, ContentBlockSchema, PromptMessageSchema, GetPromptResultSchema, PromptListChangedNotificationSchema, ToolAnnotationsSchema, ToolExecutionSchema, ToolSchema, ListToolsRequestSchema, ListToolsResultSchema, CallToolResultSchema, CompatibilityCallToolResultSchema, CallToolRequestParamsSchema, CallToolRequestSchema, ToolListChangedNotificationSchema, ListChangedOptionsBaseSchema, LoggingLevelSchema, SetLevelRequestParamsSchema, SetLevelRequestSchema, LoggingMessageNotificationParamsSchema, LoggingMessageNotificationSchema, ModelHintSchema, ModelPreferencesSchema, ToolChoiceSchema, ToolResultContentSchema, SamplingContentSchema, SamplingMessageContentBlockSchema, SamplingMessageSchema, CreateMessageRequestParamsSchema, CreateMessageRequestSchema, CreateMessageResultSchema, CreateMessageResultWithToolsSchema, BooleanSchemaSchema, StringSchemaSchema, NumberSchemaSchema, UntitledSingleSelectEnumSchemaSchema, TitledSingleSelectEnumSchemaSchema, LegacyTitledEnumSchemaSchema, SingleSelectEnumSchemaSchema, UntitledMultiSelectEnumSchemaSchema, TitledMultiSelectEnumSchemaSchema, MultiSelectEnumSchemaSchema, EnumSchemaSchema, PrimitiveSchemaDefinitionSchema, ElicitRequestFormParamsSchema, ElicitRequestURLParamsSchema, ElicitRequestParamsSchema, ElicitRequestSchema, ElicitationCompleteNotificationParamsSchema, ElicitationCompleteNotificationSchema, ElicitResultSchema, ResourceTemplateReferenceSchema, PromptReferenceSchema, CompleteRequestParamsSchema, CompleteRequestSchema, CompleteResultSchema, RootSchema, ListRootsRequestSchema, ListRootsResultSchema, RootsListChangedNotificationSchema, ClientRequestSchema, ClientNotificationSchema, ClientResultSchema, ServerRequestSchema, ServerNotificationSchema, ServerResultSchema, McpError, UrlElicitationRequiredError;
|
|
14450
14450
|
var init_types = __esm({
|
|
14451
|
-
"node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
14451
|
+
"node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js"() {
|
|
14452
14452
|
"use strict";
|
|
14453
14453
|
init_v4();
|
|
14454
14454
|
LATEST_PROTOCOL_VERSION = "2025-11-25";
|
|
@@ -14460,10 +14460,9 @@ var init_types = __esm({
|
|
|
14460
14460
|
CursorSchema = string2();
|
|
14461
14461
|
TaskCreationParamsSchema = looseObject({
|
|
14462
14462
|
/**
|
|
14463
|
-
*
|
|
14464
|
-
* If null, the task has unlimited lifetime until manually cleaned up.
|
|
14463
|
+
* Requested duration in milliseconds to retain task from creation.
|
|
14465
14464
|
*/
|
|
14466
|
-
ttl:
|
|
14465
|
+
ttl: number2().optional(),
|
|
14467
14466
|
/**
|
|
14468
14467
|
* Time in milliseconds to wait between task status requests.
|
|
14469
14468
|
*/
|
|
@@ -14762,7 +14761,11 @@ var init_types = __esm({
|
|
|
14762
14761
|
/**
|
|
14763
14762
|
* Present if the client supports task creation.
|
|
14764
14763
|
*/
|
|
14765
|
-
tasks: ClientTasksCapabilitySchema.optional()
|
|
14764
|
+
tasks: ClientTasksCapabilitySchema.optional(),
|
|
14765
|
+
/**
|
|
14766
|
+
* Extensions that the client supports. Keys are extension identifiers (vendor-prefix/extension-name).
|
|
14767
|
+
*/
|
|
14768
|
+
extensions: record(string2(), AssertObjectSchema).optional()
|
|
14766
14769
|
});
|
|
14767
14770
|
InitializeRequestParamsSchema = BaseRequestParamsSchema.extend({
|
|
14768
14771
|
/**
|
|
@@ -14823,7 +14826,11 @@ var init_types = __esm({
|
|
|
14823
14826
|
/**
|
|
14824
14827
|
* Present if the server supports task creation.
|
|
14825
14828
|
*/
|
|
14826
|
-
tasks: ServerTasksCapabilitySchema.optional()
|
|
14829
|
+
tasks: ServerTasksCapabilitySchema.optional(),
|
|
14830
|
+
/**
|
|
14831
|
+
* Extensions that the server supports. Keys are extension identifiers (vendor-prefix/extension-name).
|
|
14832
|
+
*/
|
|
14833
|
+
extensions: record(string2(), AssertObjectSchema).optional()
|
|
14827
14834
|
});
|
|
14828
14835
|
InitializeResultSchema = ResultSchema.extend({
|
|
14829
14836
|
/**
|
|
@@ -15015,6 +15022,12 @@ var init_types = __esm({
|
|
|
15015
15022
|
* The MIME type of this resource, if known.
|
|
15016
15023
|
*/
|
|
15017
15024
|
mimeType: optional(string2()),
|
|
15025
|
+
/**
|
|
15026
|
+
* The size of the raw resource content, in bytes (i.e., before base64 encoding or any tokenization), if known.
|
|
15027
|
+
*
|
|
15028
|
+
* This can be used by Hosts to display file sizes and estimate context window usage.
|
|
15029
|
+
*/
|
|
15030
|
+
size: optional(number2()),
|
|
15018
15031
|
/**
|
|
15019
15032
|
* Optional annotations for the client.
|
|
15020
15033
|
*/
|
|
@@ -22747,7 +22760,7 @@ var init_utils = __esm({
|
|
|
22747
22760
|
});
|
|
22748
22761
|
|
|
22749
22762
|
// src/internal/graphql.ts
|
|
22750
|
-
var LIST_BEANS_QUERY, CREATE_BEAN_MUTATION, UPDATE_BEAN_MUTATION, UPDATE_BEAN_MUTATION_WITH_IF_MATCH, DELETE_BEAN_MUTATION;
|
|
22763
|
+
var LIST_BEANS_QUERY, CREATE_BEAN_MUTATION, UPDATE_BEAN_MUTATION, UPDATE_BEAN_MUTATION_WITH_IF_MATCH, DELETE_BEAN_MUTATION, LIST_BEANS_TIMESTAMPS_QUERY;
|
|
22751
22764
|
var init_graphql = __esm({
|
|
22752
22765
|
"src/internal/graphql.ts"() {
|
|
22753
22766
|
"use strict";
|
|
@@ -22775,6 +22788,11 @@ var init_graphql = __esm({
|
|
|
22775
22788
|
mutation($id: ID!) {
|
|
22776
22789
|
deleteBean(id: $id)
|
|
22777
22790
|
}
|
|
22791
|
+
`;
|
|
22792
|
+
LIST_BEANS_TIMESTAMPS_QUERY = `
|
|
22793
|
+
query {
|
|
22794
|
+
beans { id updatedAt }
|
|
22795
|
+
}
|
|
22778
22796
|
`;
|
|
22779
22797
|
}
|
|
22780
22798
|
});
|
|
@@ -22797,12 +22815,26 @@ var init_backend = __esm({
|
|
|
22797
22815
|
init_graphql();
|
|
22798
22816
|
init_utils();
|
|
22799
22817
|
execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
22800
|
-
BeansCliBackend = class {
|
|
22818
|
+
BeansCliBackend = class _BeansCliBackend {
|
|
22801
22819
|
constructor(workspaceRoot, cliPath, logDir) {
|
|
22802
22820
|
this.workspaceRoot = workspaceRoot;
|
|
22803
22821
|
this.cliPath = cliPath;
|
|
22804
22822
|
this.logDir = logDir;
|
|
22805
22823
|
}
|
|
22824
|
+
// ---------------------------------------------------------------------------
|
|
22825
|
+
// Cache
|
|
22826
|
+
// ---------------------------------------------------------------------------
|
|
22827
|
+
/** Full unfiltered records keyed by bean ID, stored under the fixed cache key `'all'`. */
|
|
22828
|
+
_cache = /* @__PURE__ */ new Map();
|
|
22829
|
+
/** Last time the unfiltered cache entry `'all'` was fetched (ms). */
|
|
22830
|
+
_cacheTime = /* @__PURE__ */ new Map();
|
|
22831
|
+
/** Short-circuit TTL: skip even the timestamp check within this window (ms). */
|
|
22832
|
+
static BURST_TTL_MS = 5e3;
|
|
22833
|
+
/** Invalidate the unfiltered list cache so the next call does a full fetch. */
|
|
22834
|
+
invalidateCache() {
|
|
22835
|
+
this._cache.delete("all");
|
|
22836
|
+
this._cacheTime.delete("all");
|
|
22837
|
+
}
|
|
22806
22838
|
/**
|
|
22807
22839
|
* Returns a safe environment for executing the Beans CLI,
|
|
22808
22840
|
* whitelisting only necessary variables.
|
|
@@ -22826,7 +22858,7 @@ var init_backend = __esm({
|
|
|
22826
22858
|
return (0, import_node_path2.resolve)(this.workspaceRoot, ".beans");
|
|
22827
22859
|
}
|
|
22828
22860
|
resolveBeanFilePath(relativePath) {
|
|
22829
|
-
const cleaned = relativePath.trim().replace(/^\/+/, "");
|
|
22861
|
+
const cleaned = relativePath.trim().replace(/^\/+/, "").replace(/^\.beans(?:[\\/]|$)/, "");
|
|
22830
22862
|
if (!cleaned) {
|
|
22831
22863
|
throw new Error("Path is required");
|
|
22832
22864
|
}
|
|
@@ -22873,6 +22905,26 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22873
22905
|
});
|
|
22874
22906
|
return { initialized: true };
|
|
22875
22907
|
}
|
|
22908
|
+
async archive() {
|
|
22909
|
+
const { stdout } = await execFileAsync(this.cliPath, ["archive", "--json"], {
|
|
22910
|
+
cwd: this.workspaceRoot,
|
|
22911
|
+
env: this.getSafeEnv(),
|
|
22912
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
22913
|
+
timeout: 3e4
|
|
22914
|
+
});
|
|
22915
|
+
this.invalidateCache();
|
|
22916
|
+
if (!stdout.trim()) {
|
|
22917
|
+
return { archived: true };
|
|
22918
|
+
}
|
|
22919
|
+
try {
|
|
22920
|
+
return JSON.parse(stdout);
|
|
22921
|
+
} catch {
|
|
22922
|
+
return { archived: true, output: stdout.trim() };
|
|
22923
|
+
}
|
|
22924
|
+
}
|
|
22925
|
+
async queryGraphql(query, variables) {
|
|
22926
|
+
return this.executeGraphQL(query, variables);
|
|
22927
|
+
}
|
|
22876
22928
|
async list(options) {
|
|
22877
22929
|
const filter = {};
|
|
22878
22930
|
if (options?.status && options.status.length > 0) {
|
|
@@ -22884,10 +22936,48 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22884
22936
|
if (options?.search) {
|
|
22885
22937
|
filter.search = options.search;
|
|
22886
22938
|
}
|
|
22939
|
+
const isCacheable = !filter.status && !filter.type && !filter.search;
|
|
22940
|
+
const cacheKey = "all";
|
|
22941
|
+
if (isCacheable) {
|
|
22942
|
+
const lastFetch = this._cacheTime.get(cacheKey) ?? 0;
|
|
22943
|
+
const cached2 = this._cache.get(cacheKey);
|
|
22944
|
+
const age = Date.now() - lastFetch;
|
|
22945
|
+
if (cached2 && age < _BeansCliBackend.BURST_TTL_MS) {
|
|
22946
|
+
return Array.from(cached2.values());
|
|
22947
|
+
}
|
|
22948
|
+
if (cached2) {
|
|
22949
|
+
try {
|
|
22950
|
+
const { data: tsData } = await this.executeGraphQL(
|
|
22951
|
+
LIST_BEANS_TIMESTAMPS_QUERY
|
|
22952
|
+
);
|
|
22953
|
+
const timestamps = tsData.beans;
|
|
22954
|
+
let dirty = timestamps.length !== cached2.size;
|
|
22955
|
+
if (!dirty) {
|
|
22956
|
+
for (const { id, updatedAt } of timestamps) {
|
|
22957
|
+
const existing = cached2.get(id);
|
|
22958
|
+
if (!existing || existing.updatedAt !== updatedAt) {
|
|
22959
|
+
dirty = true;
|
|
22960
|
+
break;
|
|
22961
|
+
}
|
|
22962
|
+
}
|
|
22963
|
+
}
|
|
22964
|
+
if (!dirty) {
|
|
22965
|
+
this._cacheTime.set(cacheKey, Date.now());
|
|
22966
|
+
return Array.from(cached2.values());
|
|
22967
|
+
}
|
|
22968
|
+
} catch {
|
|
22969
|
+
}
|
|
22970
|
+
}
|
|
22971
|
+
}
|
|
22887
22972
|
const { data, errors } = await this.executeGraphQL(LIST_BEANS_QUERY, { filter });
|
|
22888
22973
|
if (errors && errors.length > 0) {
|
|
22889
22974
|
throw new Error(`GraphQL error: ${errors.map((e) => e.message).join(", ")}`);
|
|
22890
22975
|
}
|
|
22976
|
+
if (isCacheable) {
|
|
22977
|
+
const byId = new Map(data.beans.map((b) => [b.id, b]));
|
|
22978
|
+
this._cache.set(cacheKey, byId);
|
|
22979
|
+
this._cacheTime.set(cacheKey, Date.now());
|
|
22980
|
+
}
|
|
22891
22981
|
return data.beans;
|
|
22892
22982
|
}
|
|
22893
22983
|
async create(input) {
|
|
@@ -22896,7 +22986,7 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22896
22986
|
type: input.type,
|
|
22897
22987
|
status: input.status,
|
|
22898
22988
|
priority: input.priority,
|
|
22899
|
-
body: input.description,
|
|
22989
|
+
body: input.body ?? input.description,
|
|
22900
22990
|
parent: input.parent
|
|
22901
22991
|
};
|
|
22902
22992
|
const { data, errors } = await this.executeGraphQL(CREATE_BEAN_MUTATION, {
|
|
@@ -22905,6 +22995,7 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22905
22995
|
if (errors && errors.length > 0) {
|
|
22906
22996
|
throw new Error(`GraphQL error: ${errors.map((e) => e.message).join(", ")}`);
|
|
22907
22997
|
}
|
|
22998
|
+
this.invalidateCache();
|
|
22908
22999
|
return data.createBean;
|
|
22909
23000
|
}
|
|
22910
23001
|
async update(beanId, updates) {
|
|
@@ -22974,6 +23065,7 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22974
23065
|
if (errors && errors.length > 0) {
|
|
22975
23066
|
throw new Error(`GraphQL error: ${errors.map((e) => e.message).join(", ")}`);
|
|
22976
23067
|
}
|
|
23068
|
+
this.invalidateCache();
|
|
22977
23069
|
return data.updateBean;
|
|
22978
23070
|
}
|
|
22979
23071
|
async delete(beanId) {
|
|
@@ -22983,8 +23075,44 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22983
23075
|
if (errors && errors.length > 0) {
|
|
22984
23076
|
throw new Error(`GraphQL error: ${errors.map((e) => e.message).join(", ")}`);
|
|
22985
23077
|
}
|
|
23078
|
+
this.invalidateCache();
|
|
22986
23079
|
return { deleted: true, beanId };
|
|
22987
23080
|
}
|
|
23081
|
+
async bulkCreate(beans, defaultParent) {
|
|
23082
|
+
const settled = await Promise.allSettled(
|
|
23083
|
+
beans.map(
|
|
23084
|
+
async (item) => this.create({
|
|
23085
|
+
...item,
|
|
23086
|
+
parent: item.parent ?? defaultParent
|
|
23087
|
+
})
|
|
23088
|
+
)
|
|
23089
|
+
);
|
|
23090
|
+
return settled.map(
|
|
23091
|
+
(result) => result.status === "fulfilled" ? { bean: result.value } : { error: result.reason instanceof Error ? result.reason.message : String(result.reason) }
|
|
23092
|
+
);
|
|
23093
|
+
}
|
|
23094
|
+
async bulkUpdate(beans, defaultParent) {
|
|
23095
|
+
const settled = await Promise.allSettled(
|
|
23096
|
+
beans.map(async ({ beanId, ...updates }) => {
|
|
23097
|
+
const resolvedParent = updates.parent ?? (updates.clearParent ? void 0 : defaultParent);
|
|
23098
|
+
const bean = await this.update(beanId, { ...updates, parent: resolvedParent });
|
|
23099
|
+
return { beanId, bean };
|
|
23100
|
+
})
|
|
23101
|
+
);
|
|
23102
|
+
return settled.map((result, index) => {
|
|
23103
|
+
const beanId = beans[index]?.beanId;
|
|
23104
|
+
if (!beanId) {
|
|
23105
|
+
return { beanId: "unknown", error: "Unknown bean id" };
|
|
23106
|
+
}
|
|
23107
|
+
if (result.status === "fulfilled") {
|
|
23108
|
+
return result.value;
|
|
23109
|
+
}
|
|
23110
|
+
return {
|
|
23111
|
+
beanId,
|
|
23112
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
23113
|
+
};
|
|
23114
|
+
});
|
|
23115
|
+
}
|
|
22988
23116
|
async openConfig() {
|
|
22989
23117
|
const configPath = (0, import_node_path2.join)(this.workspaceRoot, ".beans.yml");
|
|
22990
23118
|
const content = await (0, import_promises.readFile)(configPath, "utf8");
|
|
@@ -23018,9 +23146,12 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
23018
23146
|
const outputPath = (0, import_node_path2.resolve)(
|
|
23019
23147
|
process.env.BEANS_VSCODE_OUTPUT_LOG || (0, import_node_path2.join)(this.workspaceRoot, ".vscode", "logs", "beans-output.log")
|
|
23020
23148
|
);
|
|
23021
|
-
const
|
|
23149
|
+
const canonicalOutputPath = await (0, import_promises.realpath)(outputPath).catch(() => outputPath);
|
|
23150
|
+
const canonicalWorkspaceRoot = await (0, import_promises.realpath)(this.workspaceRoot).catch(() => (0, import_node_path2.resolve)(this.workspaceRoot));
|
|
23151
|
+
const isWithinWorkspace = isPathWithinRoot(canonicalWorkspaceRoot, canonicalOutputPath);
|
|
23022
23152
|
const vscodeLogDir = process.env.BEANS_VSCODE_LOG_DIR || this.logDir ? (0, import_node_path2.resolve)(process.env.BEANS_VSCODE_LOG_DIR || this.logDir || "") : void 0;
|
|
23023
|
-
const
|
|
23153
|
+
const canonicalVscodeLogDir = vscodeLogDir ? await (0, import_promises.realpath)(vscodeLogDir).catch(() => (0, import_node_path2.resolve)(vscodeLogDir)) : void 0;
|
|
23154
|
+
const isWithinVscodeLogDir = canonicalVscodeLogDir ? isPathWithinRoot(canonicalVscodeLogDir, canonicalOutputPath) : false;
|
|
23024
23155
|
if (!isWithinWorkspace && !isWithinVscodeLogDir) {
|
|
23025
23156
|
throw new Error("Output log path must stay within the workspace or VS Code log directory");
|
|
23026
23157
|
}
|
|
@@ -23043,6 +23174,219 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
23043
23174
|
linesReturned: ringBuffer.length
|
|
23044
23175
|
};
|
|
23045
23176
|
}
|
|
23177
|
+
/**
|
|
23178
|
+
* Split a YAML scalar value from any trailing inline comment.
|
|
23179
|
+
* Understands single-quoted and double-quoted YAML strings so it won't
|
|
23180
|
+
* mistake a `#` inside a quoted value for a comment delimiter.
|
|
23181
|
+
*/
|
|
23182
|
+
splitYamlInlineComment(value) {
|
|
23183
|
+
let inSingle = false;
|
|
23184
|
+
let inDouble = false;
|
|
23185
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
23186
|
+
const char = value[i];
|
|
23187
|
+
if (inSingle) {
|
|
23188
|
+
if (char === "'") {
|
|
23189
|
+
if (value[i + 1] === "'") {
|
|
23190
|
+
i += 1;
|
|
23191
|
+
} else {
|
|
23192
|
+
inSingle = false;
|
|
23193
|
+
}
|
|
23194
|
+
}
|
|
23195
|
+
continue;
|
|
23196
|
+
}
|
|
23197
|
+
if (inDouble) {
|
|
23198
|
+
if (char === "\\") {
|
|
23199
|
+
i += 1;
|
|
23200
|
+
continue;
|
|
23201
|
+
}
|
|
23202
|
+
if (char === '"') {
|
|
23203
|
+
inDouble = false;
|
|
23204
|
+
}
|
|
23205
|
+
continue;
|
|
23206
|
+
}
|
|
23207
|
+
if (char === "'") {
|
|
23208
|
+
inSingle = true;
|
|
23209
|
+
continue;
|
|
23210
|
+
}
|
|
23211
|
+
if (char === '"') {
|
|
23212
|
+
inDouble = true;
|
|
23213
|
+
continue;
|
|
23214
|
+
}
|
|
23215
|
+
if (char === "#" && i > 0 && /\s/.test(value[i - 1])) {
|
|
23216
|
+
const valuePart = value.slice(0, i).trimEnd();
|
|
23217
|
+
return {
|
|
23218
|
+
valuePart,
|
|
23219
|
+
commentPart: value.slice(valuePart.length)
|
|
23220
|
+
};
|
|
23221
|
+
}
|
|
23222
|
+
}
|
|
23223
|
+
return { valuePart: value, commentPart: "" };
|
|
23224
|
+
}
|
|
23225
|
+
/** Returns true when `value` looks like a YAML block scalar indicator (`>`, `|`, `>-`, `|-`, etc.) */
|
|
23226
|
+
isYamlBlockScalarIndicator(value) {
|
|
23227
|
+
return /^[>|][+-]?[0-9]*$/.test(value) || /^[>|][0-9]*[+-]?$/.test(value);
|
|
23228
|
+
}
|
|
23229
|
+
/** Escape a plain string for use inside a YAML double-quoted scalar. */
|
|
23230
|
+
escapeForYamlDoubleQuoted(value) {
|
|
23231
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
23232
|
+
}
|
|
23233
|
+
shouldQuoteFrontmatterValue(value) {
|
|
23234
|
+
return !/^[A-Za-z0-9._-]+$/.test(value);
|
|
23235
|
+
}
|
|
23236
|
+
parseFrontmatterLine(line) {
|
|
23237
|
+
const separatorIndex = line.indexOf(":");
|
|
23238
|
+
if (separatorIndex <= 0) {
|
|
23239
|
+
return null;
|
|
23240
|
+
}
|
|
23241
|
+
const key = line.slice(0, separatorIndex).trim();
|
|
23242
|
+
if (key.length === 0) {
|
|
23243
|
+
return null;
|
|
23244
|
+
}
|
|
23245
|
+
for (const character of key) {
|
|
23246
|
+
const isAlphaNumericUnderscore = character >= "a" && character <= "z" || character >= "A" && character <= "Z" || character >= "0" && character <= "9" || character === "_";
|
|
23247
|
+
if (!isAlphaNumericUnderscore) {
|
|
23248
|
+
return null;
|
|
23249
|
+
}
|
|
23250
|
+
}
|
|
23251
|
+
const rawValue = line.slice(separatorIndex + 1).trimStart();
|
|
23252
|
+
return { key, rawValue };
|
|
23253
|
+
}
|
|
23254
|
+
buildFrontmatterIndex(frontmatterLines) {
|
|
23255
|
+
const indexByKey = /* @__PURE__ */ new Map();
|
|
23256
|
+
frontmatterLines.forEach((line, index) => {
|
|
23257
|
+
const parsed = this.parseFrontmatterLine(line);
|
|
23258
|
+
if (!parsed) {
|
|
23259
|
+
return;
|
|
23260
|
+
}
|
|
23261
|
+
indexByKey.set(parsed.key, index);
|
|
23262
|
+
});
|
|
23263
|
+
return indexByKey;
|
|
23264
|
+
}
|
|
23265
|
+
serializeFrontmatterValue(key, value) {
|
|
23266
|
+
if (Array.isArray(value)) {
|
|
23267
|
+
return JSON.stringify(value);
|
|
23268
|
+
}
|
|
23269
|
+
if (key === "title") {
|
|
23270
|
+
return this.normalizeFrontmatterTitleValue(value);
|
|
23271
|
+
}
|
|
23272
|
+
if (this.shouldQuoteFrontmatterValue(value)) {
|
|
23273
|
+
return `"${this.escapeForYamlDoubleQuoted(value)}"`;
|
|
23274
|
+
}
|
|
23275
|
+
return value;
|
|
23276
|
+
}
|
|
23277
|
+
deserializeFrontmatterValue(value) {
|
|
23278
|
+
const trimmed = value.trim();
|
|
23279
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
23280
|
+
try {
|
|
23281
|
+
const parsed = JSON.parse(trimmed);
|
|
23282
|
+
if (Array.isArray(parsed) && parsed.every((item) => typeof item === "string")) {
|
|
23283
|
+
return parsed;
|
|
23284
|
+
}
|
|
23285
|
+
} catch {
|
|
23286
|
+
}
|
|
23287
|
+
}
|
|
23288
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
23289
|
+
return trimmed.slice(1, -1).replaceAll('\\"', '"').replaceAll("\\\\", "\\").replaceAll("''", "'");
|
|
23290
|
+
}
|
|
23291
|
+
return trimmed;
|
|
23292
|
+
}
|
|
23293
|
+
splitFrontmatterDocument(content) {
|
|
23294
|
+
const crlfOpen = content.startsWith("---\r\n");
|
|
23295
|
+
const lfOpen = content.startsWith("---\n");
|
|
23296
|
+
const eol = crlfOpen ? "\r\n" : "\n";
|
|
23297
|
+
if (!crlfOpen && !lfOpen) {
|
|
23298
|
+
return { eol: "\n", hasFrontmatter: false, frontmatterLines: [], body: content };
|
|
23299
|
+
}
|
|
23300
|
+
const openEnd = `---${eol}`.length;
|
|
23301
|
+
const closeMarker = `${eol}---`;
|
|
23302
|
+
const closeIdx = content.indexOf(closeMarker, openEnd);
|
|
23303
|
+
if (closeIdx === -1) {
|
|
23304
|
+
return { eol, hasFrontmatter: false, frontmatterLines: [], body: content };
|
|
23305
|
+
}
|
|
23306
|
+
const frontmatter = content.slice(openEnd, closeIdx);
|
|
23307
|
+
const body = content.slice(closeIdx + closeMarker.length);
|
|
23308
|
+
return {
|
|
23309
|
+
eol,
|
|
23310
|
+
hasFrontmatter: true,
|
|
23311
|
+
frontmatterLines: frontmatter.length > 0 ? frontmatter.split(eol) : [],
|
|
23312
|
+
body
|
|
23313
|
+
};
|
|
23314
|
+
}
|
|
23315
|
+
parseFrontmatterFields(frontmatterLines) {
|
|
23316
|
+
const fields = {};
|
|
23317
|
+
for (const line of frontmatterLines) {
|
|
23318
|
+
const parsed = this.parseFrontmatterLine(line);
|
|
23319
|
+
if (!parsed) {
|
|
23320
|
+
continue;
|
|
23321
|
+
}
|
|
23322
|
+
const { valuePart } = this.splitYamlInlineComment(parsed.rawValue);
|
|
23323
|
+
fields[parsed.key] = this.deserializeFrontmatterValue(valuePart);
|
|
23324
|
+
}
|
|
23325
|
+
return fields;
|
|
23326
|
+
}
|
|
23327
|
+
async writeFileAtomically(absolutePath, content) {
|
|
23328
|
+
const tempPath = `${absolutePath}.tmp-${process.pid}-${Date.now()}`;
|
|
23329
|
+
await (0, import_promises.writeFile)(tempPath, content, "utf8");
|
|
23330
|
+
await (0, import_promises.rename)(tempPath, absolutePath);
|
|
23331
|
+
}
|
|
23332
|
+
/**
|
|
23333
|
+
* Normalise a raw YAML title value to a double-quoted scalar.
|
|
23334
|
+
* Handles: empty, already double-quoted, single-quoted (unescaping `''`),
|
|
23335
|
+
* block-scalar indicators, and plain unquoted values.
|
|
23336
|
+
*/
|
|
23337
|
+
normalizeFrontmatterTitleValue(value) {
|
|
23338
|
+
const trimmed = value.trim();
|
|
23339
|
+
if (trimmed === "") {
|
|
23340
|
+
return '""';
|
|
23341
|
+
}
|
|
23342
|
+
if (this.isYamlBlockScalarIndicator(trimmed)) {
|
|
23343
|
+
return value;
|
|
23344
|
+
}
|
|
23345
|
+
if (/^"(?:[^"\\]|\\[\s\S])*"$/.test(trimmed)) {
|
|
23346
|
+
return trimmed;
|
|
23347
|
+
}
|
|
23348
|
+
if (/^'(?:[^']|'')*'$/.test(trimmed)) {
|
|
23349
|
+
const inner = trimmed.slice(1, -1).replace(/''/g, "'");
|
|
23350
|
+
return `"${this.escapeForYamlDoubleQuoted(inner)}"`;
|
|
23351
|
+
}
|
|
23352
|
+
return `"${this.escapeForYamlDoubleQuoted(trimmed)}"`;
|
|
23353
|
+
}
|
|
23354
|
+
/**
|
|
23355
|
+
* Ensure every `title:` line in YAML frontmatter is double-quoted.
|
|
23356
|
+
* Handles already-quoted (single or double), multi-word, and special-char values.
|
|
23357
|
+
* Preserves inline comments and handles both LF and CRLF line endings.
|
|
23358
|
+
*/
|
|
23359
|
+
quoteFrontmatterTitles(content) {
|
|
23360
|
+
const crlfOpen = content.startsWith("---\r\n");
|
|
23361
|
+
const lfOpen = content.startsWith("---\n");
|
|
23362
|
+
if (!crlfOpen && !lfOpen) {
|
|
23363
|
+
return content;
|
|
23364
|
+
}
|
|
23365
|
+
const eol = crlfOpen ? "\r\n" : "\n";
|
|
23366
|
+
const openEnd = `---${eol}`.length;
|
|
23367
|
+
const closeMarker = `${eol}---`;
|
|
23368
|
+
const closeIdx = content.indexOf(closeMarker, openEnd);
|
|
23369
|
+
if (closeIdx === -1) {
|
|
23370
|
+
return content;
|
|
23371
|
+
}
|
|
23372
|
+
const frontmatter = content.slice(openEnd, closeIdx);
|
|
23373
|
+
const rest = content.slice(closeIdx);
|
|
23374
|
+
const lines = frontmatter.split(eol);
|
|
23375
|
+
const fixedLines = lines.map((line) => {
|
|
23376
|
+
if (!line.startsWith("title:")) {
|
|
23377
|
+
return line;
|
|
23378
|
+
}
|
|
23379
|
+
const colonIdx = line.indexOf(":");
|
|
23380
|
+
const afterColon = line.slice(colonIdx + 1);
|
|
23381
|
+
const leadingSpace = afterColon.length - afterColon.trimStart().length;
|
|
23382
|
+
const raw = afterColon.trimStart();
|
|
23383
|
+
const { valuePart, commentPart } = this.splitYamlInlineComment(raw);
|
|
23384
|
+
const normalized = this.normalizeFrontmatterTitleValue(valuePart);
|
|
23385
|
+
const prefix = `title:${" ".repeat(Math.max(1, leadingSpace))}`;
|
|
23386
|
+
return `${prefix}${normalized}${commentPart}`;
|
|
23387
|
+
});
|
|
23388
|
+
return `---${eol}${fixedLines.join(eol)}${rest}`;
|
|
23389
|
+
}
|
|
23046
23390
|
async readBeanFile(relativePath) {
|
|
23047
23391
|
const absolutePath = this.resolveBeanFilePath(relativePath);
|
|
23048
23392
|
const content = await (0, import_promises.readFile)(absolutePath, "utf8");
|
|
@@ -23050,20 +23394,74 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
23050
23394
|
}
|
|
23051
23395
|
async editBeanFile(relativePath, content) {
|
|
23052
23396
|
const absolutePath = this.resolveBeanFilePath(relativePath);
|
|
23397
|
+
const fixed = this.quoteFrontmatterTitles(content);
|
|
23053
23398
|
await (0, import_promises.mkdir)((0, import_node_path2.dirname)(absolutePath), { recursive: true });
|
|
23054
|
-
await (0, import_promises.writeFile)(absolutePath,
|
|
23055
|
-
return { path: absolutePath, bytes: Buffer.byteLength(
|
|
23399
|
+
await (0, import_promises.writeFile)(absolutePath, fixed, "utf8");
|
|
23400
|
+
return { path: absolutePath, bytes: Buffer.byteLength(fixed, "utf8") };
|
|
23401
|
+
}
|
|
23402
|
+
async updateBeanFrontmatter(relativePath, updates) {
|
|
23403
|
+
const absolutePath = this.resolveBeanFilePath(relativePath);
|
|
23404
|
+
const content = await (0, import_promises.readFile)(absolutePath, "utf8");
|
|
23405
|
+
const { eol, hasFrontmatter, frontmatterLines, body } = this.splitFrontmatterDocument(content);
|
|
23406
|
+
const updatedFields = Object.entries(updates).filter(([, value]) => value !== void 0).map(([key]) => key);
|
|
23407
|
+
if (updatedFields.length === 0) {
|
|
23408
|
+
throw new Error("At least one frontmatter field update is required");
|
|
23409
|
+
}
|
|
23410
|
+
const nextLines = [...frontmatterLines];
|
|
23411
|
+
let indexByKey = this.buildFrontmatterIndex(nextLines);
|
|
23412
|
+
for (const [key, value] of Object.entries(updates)) {
|
|
23413
|
+
if (value === void 0) {
|
|
23414
|
+
continue;
|
|
23415
|
+
}
|
|
23416
|
+
const existingIndex = indexByKey.get(key);
|
|
23417
|
+
if (value === null) {
|
|
23418
|
+
if (existingIndex !== void 0) {
|
|
23419
|
+
nextLines.splice(existingIndex, 1);
|
|
23420
|
+
indexByKey = this.buildFrontmatterIndex(nextLines);
|
|
23421
|
+
}
|
|
23422
|
+
continue;
|
|
23423
|
+
}
|
|
23424
|
+
const serialized = `${key}: ${this.serializeFrontmatterValue(key, value)}`;
|
|
23425
|
+
if (existingIndex !== void 0) {
|
|
23426
|
+
const existingLine = nextLines[existingIndex] ?? "";
|
|
23427
|
+
const existingParsed = this.parseFrontmatterLine(existingLine);
|
|
23428
|
+
const commentPart = existingParsed ? this.splitYamlInlineComment(existingParsed.rawValue).commentPart : "";
|
|
23429
|
+
nextLines[existingIndex] = `${serialized}${commentPart}`;
|
|
23430
|
+
} else {
|
|
23431
|
+
nextLines.push(serialized);
|
|
23432
|
+
indexByKey.set(key, nextLines.length - 1);
|
|
23433
|
+
}
|
|
23434
|
+
}
|
|
23435
|
+
const frontmatterBlock = nextLines.length > 0 ? nextLines.join(eol) : "";
|
|
23436
|
+
const nextContent = hasFrontmatter ? `---${eol}${frontmatterBlock}${eol}---${body}` : `---${eol}${frontmatterBlock}${eol}---${eol}${body}`;
|
|
23437
|
+
const fixed = this.quoteFrontmatterTitles(nextContent);
|
|
23438
|
+
await this.writeFileAtomically(absolutePath, fixed);
|
|
23439
|
+
return {
|
|
23440
|
+
path: absolutePath,
|
|
23441
|
+
bytes: Buffer.byteLength(fixed, "utf8"),
|
|
23442
|
+
updatedFields,
|
|
23443
|
+
frontmatter: this.parseFrontmatterFields(this.splitFrontmatterDocument(fixed).frontmatterLines)
|
|
23444
|
+
};
|
|
23056
23445
|
}
|
|
23057
23446
|
async createBeanFile(relativePath, content, options) {
|
|
23058
23447
|
const absolutePath = this.resolveBeanFilePath(relativePath);
|
|
23448
|
+
const fixed = this.quoteFrontmatterTitles(content);
|
|
23059
23449
|
await (0, import_promises.mkdir)((0, import_node_path2.dirname)(absolutePath), { recursive: true });
|
|
23060
|
-
|
|
23061
|
-
|
|
23062
|
-
|
|
23063
|
-
|
|
23450
|
+
try {
|
|
23451
|
+
await (0, import_promises.writeFile)(absolutePath, fixed, {
|
|
23452
|
+
encoding: "utf8",
|
|
23453
|
+
flag: options?.overwrite ? "w" : "wx"
|
|
23454
|
+
});
|
|
23455
|
+
} catch (error48) {
|
|
23456
|
+
const maybeNodeError = error48;
|
|
23457
|
+
if (maybeNodeError.code === "EEXIST" && !options?.overwrite) {
|
|
23458
|
+
throw new Error("Bean file already exists. Pass overwrite=true to replace it.");
|
|
23459
|
+
}
|
|
23460
|
+
throw error48;
|
|
23461
|
+
}
|
|
23064
23462
|
return {
|
|
23065
23463
|
path: absolutePath,
|
|
23066
|
-
bytes: Buffer.byteLength(
|
|
23464
|
+
bytes: Buffer.byteLength(fixed, "utf8"),
|
|
23067
23465
|
created: true
|
|
23068
23466
|
};
|
|
23069
23467
|
}
|
|
@@ -23076,7 +23474,7 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
23076
23474
|
}
|
|
23077
23475
|
});
|
|
23078
23476
|
|
|
23079
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
23477
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
|
|
23080
23478
|
function deserializeMessage(line) {
|
|
23081
23479
|
return JSONRPCMessageSchema.parse(JSON.parse(line));
|
|
23082
23480
|
}
|
|
@@ -23085,7 +23483,7 @@ function serializeMessage(message) {
|
|
|
23085
23483
|
}
|
|
23086
23484
|
var ReadBuffer;
|
|
23087
23485
|
var init_stdio = __esm({
|
|
23088
|
-
"node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
23486
|
+
"node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js"() {
|
|
23089
23487
|
"use strict";
|
|
23090
23488
|
init_types();
|
|
23091
23489
|
ReadBuffer = class {
|
|
@@ -23111,14 +23509,14 @@ var init_stdio = __esm({
|
|
|
23111
23509
|
}
|
|
23112
23510
|
});
|
|
23113
23511
|
|
|
23114
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
23512
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
23115
23513
|
var stdio_exports = {};
|
|
23116
23514
|
__export(stdio_exports, {
|
|
23117
23515
|
StdioServerTransport: () => StdioServerTransport
|
|
23118
23516
|
});
|
|
23119
23517
|
var import_node_process, StdioServerTransport;
|
|
23120
23518
|
var init_stdio2 = __esm({
|
|
23121
|
-
"node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
23519
|
+
"node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js"() {
|
|
23122
23520
|
"use strict";
|
|
23123
23521
|
import_node_process = __toESM(require("process"), 1);
|
|
23124
23522
|
init_stdio();
|
|
@@ -23191,6 +23589,7 @@ __export(src_exports, {
|
|
|
23191
23589
|
DEFAULT_MCP_PORT: () => DEFAULT_MCP_PORT,
|
|
23192
23590
|
MAX_ID_LENGTH: () => MAX_ID_LENGTH,
|
|
23193
23591
|
MAX_METADATA_LENGTH: () => MAX_METADATA_LENGTH,
|
|
23592
|
+
MAX_PATH_LENGTH: () => MAX_PATH_LENGTH,
|
|
23194
23593
|
MAX_TITLE_LENGTH: () => MAX_TITLE_LENGTH,
|
|
23195
23594
|
createBeansMcpServer: () => createBeansMcpServer,
|
|
23196
23595
|
isPathWithinRoot: () => isPathWithinRoot,
|
|
@@ -27143,7 +27542,7 @@ init_core2();
|
|
|
27143
27542
|
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/mini/coerce.js
|
|
27144
27543
|
init_core2();
|
|
27145
27544
|
|
|
27146
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
27545
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
|
|
27147
27546
|
function isZ4Schema(s) {
|
|
27148
27547
|
const schema = s;
|
|
27149
27548
|
return !!schema._zod;
|
|
@@ -27287,10 +27686,10 @@ function getLiteralValue(schema) {
|
|
|
27287
27686
|
return void 0;
|
|
27288
27687
|
}
|
|
27289
27688
|
|
|
27290
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
27689
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
|
|
27291
27690
|
init_types();
|
|
27292
27691
|
|
|
27293
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
27692
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
|
|
27294
27693
|
function isTerminal(status) {
|
|
27295
27694
|
return status === "completed" || status === "failed" || status === "cancelled";
|
|
27296
27695
|
}
|
|
@@ -28579,7 +28978,7 @@ var zodToJsonSchema = (schema, options) => {
|
|
|
28579
28978
|
return combined;
|
|
28580
28979
|
};
|
|
28581
28980
|
|
|
28582
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
28981
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
|
|
28583
28982
|
function mapMiniTarget(t) {
|
|
28584
28983
|
if (!t)
|
|
28585
28984
|
return "draft-7";
|
|
@@ -28621,7 +29020,7 @@ function parseWithCompat(schema, data) {
|
|
|
28621
29020
|
return result.data;
|
|
28622
29021
|
}
|
|
28623
29022
|
|
|
28624
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
29023
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
|
|
28625
29024
|
var DEFAULT_REQUEST_TIMEOUT_MSEC = 6e4;
|
|
28626
29025
|
var Protocol = class {
|
|
28627
29026
|
constructor(_options) {
|
|
@@ -28833,6 +29232,10 @@ var Protocol = class {
|
|
|
28833
29232
|
this._progressHandlers.clear();
|
|
28834
29233
|
this._taskProgressTokens.clear();
|
|
28835
29234
|
this._pendingDebouncedNotifications.clear();
|
|
29235
|
+
for (const info of this._timeoutInfo.values()) {
|
|
29236
|
+
clearTimeout(info.timeoutId);
|
|
29237
|
+
}
|
|
29238
|
+
this._timeoutInfo.clear();
|
|
28836
29239
|
for (const controller of this._requestHandlerAbortControllers.values()) {
|
|
28837
29240
|
controller.abort();
|
|
28838
29241
|
}
|
|
@@ -28963,7 +29366,9 @@ var Protocol = class {
|
|
|
28963
29366
|
await capturedTransport?.send(errorResponse);
|
|
28964
29367
|
}
|
|
28965
29368
|
}).catch((error48) => this._onerror(new Error(`Failed to send response: ${error48}`))).finally(() => {
|
|
28966
|
-
this._requestHandlerAbortControllers.
|
|
29369
|
+
if (this._requestHandlerAbortControllers.get(request.id) === abortController) {
|
|
29370
|
+
this._requestHandlerAbortControllers.delete(request.id);
|
|
29371
|
+
}
|
|
28967
29372
|
});
|
|
28968
29373
|
}
|
|
28969
29374
|
_onprogress(notification) {
|
|
@@ -29569,10 +29974,10 @@ function mergeCapabilities(base, additional) {
|
|
|
29569
29974
|
return result;
|
|
29570
29975
|
}
|
|
29571
29976
|
|
|
29572
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
29977
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
|
|
29573
29978
|
init_types();
|
|
29574
29979
|
|
|
29575
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
29980
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/validation/ajv-provider.js
|
|
29576
29981
|
var import_ajv = __toESM(require_ajv(), 1);
|
|
29577
29982
|
var import_ajv_formats = __toESM(require_dist(), 1);
|
|
29578
29983
|
function createDefaultAjvInstance() {
|
|
@@ -29640,7 +30045,7 @@ var AjvJsonSchemaValidator = class {
|
|
|
29640
30045
|
}
|
|
29641
30046
|
};
|
|
29642
30047
|
|
|
29643
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30048
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/server.js
|
|
29644
30049
|
init_types();
|
|
29645
30050
|
var ExperimentalServerTasks = class {
|
|
29646
30051
|
constructor(_server) {
|
|
@@ -29854,7 +30259,7 @@ var ExperimentalServerTasks = class {
|
|
|
29854
30259
|
}
|
|
29855
30260
|
};
|
|
29856
30261
|
|
|
29857
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30262
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js
|
|
29858
30263
|
function assertToolsCallTaskCapability(requests, method, entityName) {
|
|
29859
30264
|
if (!requests) {
|
|
29860
30265
|
throw new Error(`${entityName} does not support task creation (required for ${method})`);
|
|
@@ -29889,7 +30294,7 @@ function assertClientRequestTaskCapability(requests, method, entityName) {
|
|
|
29889
30294
|
}
|
|
29890
30295
|
}
|
|
29891
30296
|
|
|
29892
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30297
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
|
|
29893
30298
|
var Server = class extends Protocol {
|
|
29894
30299
|
/**
|
|
29895
30300
|
* Initializes this server with the given name and version information.
|
|
@@ -30269,10 +30674,10 @@ var Server = class extends Protocol {
|
|
|
30269
30674
|
}
|
|
30270
30675
|
};
|
|
30271
30676
|
|
|
30272
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30677
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
|
|
30273
30678
|
init_types();
|
|
30274
30679
|
|
|
30275
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30680
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/completable.js
|
|
30276
30681
|
var COMPLETABLE_SYMBOL = /* @__PURE__ */ Symbol.for("mcp.completable");
|
|
30277
30682
|
function isCompletable(schema) {
|
|
30278
30683
|
return !!schema && typeof schema === "object" && COMPLETABLE_SYMBOL in schema;
|
|
@@ -30286,7 +30691,7 @@ var McpZodTypeKind;
|
|
|
30286
30691
|
McpZodTypeKind2["Completable"] = "McpCompletable";
|
|
30287
30692
|
})(McpZodTypeKind || (McpZodTypeKind = {}));
|
|
30288
30693
|
|
|
30289
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30694
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/toolNameValidation.js
|
|
30290
30695
|
var TOOL_NAME_REGEX = /^[A-Za-z0-9._-]{1,128}$/;
|
|
30291
30696
|
function validateToolName(name) {
|
|
30292
30697
|
const warnings = [];
|
|
@@ -30344,7 +30749,7 @@ function validateAndWarnToolName(name) {
|
|
|
30344
30749
|
return result.isValid;
|
|
30345
30750
|
}
|
|
30346
30751
|
|
|
30347
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30752
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/mcp-server.js
|
|
30348
30753
|
var ExperimentalMcpServerTasks = class {
|
|
30349
30754
|
constructor(_mcpServer) {
|
|
30350
30755
|
this._mcpServer = _mcpServer;
|
|
@@ -30363,7 +30768,7 @@ var ExperimentalMcpServerTasks = class {
|
|
|
30363
30768
|
init_external();
|
|
30364
30769
|
init_external();
|
|
30365
30770
|
|
|
30366
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30771
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
|
|
30367
30772
|
var McpServer = class {
|
|
30368
30773
|
constructor(serverInfo, options) {
|
|
30369
30774
|
this._registeredResources = {};
|
|
@@ -30987,6 +31392,9 @@ var McpServer = class {
|
|
|
30987
31392
|
annotations = rest.shift();
|
|
30988
31393
|
}
|
|
30989
31394
|
} else if (typeof firstArg === "object" && firstArg !== null) {
|
|
31395
|
+
if (Object.values(firstArg).some((v) => typeof v === "object" && v !== null)) {
|
|
31396
|
+
throw new Error(`Tool ${name} expected a Zod schema or ToolAnnotations, but received an unrecognized object`);
|
|
31397
|
+
}
|
|
30990
31398
|
annotations = rest.shift();
|
|
30991
31399
|
}
|
|
30992
31400
|
}
|
|
@@ -31105,6 +31513,9 @@ function getZodSchemaObject(schema) {
|
|
|
31105
31513
|
if (isZodRawShapeCompat(schema)) {
|
|
31106
31514
|
return objectFromShape(schema);
|
|
31107
31515
|
}
|
|
31516
|
+
if (!isZodSchemaInstance(schema)) {
|
|
31517
|
+
throw new Error("inputSchema must be a Zod schema or raw shape, received an unrecognized object");
|
|
31518
|
+
}
|
|
31108
31519
|
return schema;
|
|
31109
31520
|
}
|
|
31110
31521
|
function promptArgumentsFromSchema(schema) {
|
|
@@ -31153,6 +31564,100 @@ var EMPTY_COMPLETION_RESULT = {
|
|
|
31153
31564
|
var import_node_child_process2 = require("child_process");
|
|
31154
31565
|
var import_node_util2 = require("util");
|
|
31155
31566
|
|
|
31567
|
+
// package.json
|
|
31568
|
+
var package_default = {
|
|
31569
|
+
name: "@selfagency/beans-mcp",
|
|
31570
|
+
version: "0.6.0",
|
|
31571
|
+
private: false,
|
|
31572
|
+
description: "MCP (Model Context Protocol) server for Beans issue tracker",
|
|
31573
|
+
keywords: [
|
|
31574
|
+
"ai",
|
|
31575
|
+
"beans",
|
|
31576
|
+
"issue-tracker",
|
|
31577
|
+
"mcp",
|
|
31578
|
+
"model-context-protocol"
|
|
31579
|
+
],
|
|
31580
|
+
homepage: "https://github.com/selfagency/beans-mcp",
|
|
31581
|
+
bugs: {
|
|
31582
|
+
url: "https://github.com/selfagency/beans-mcp/issues"
|
|
31583
|
+
},
|
|
31584
|
+
license: "MIT",
|
|
31585
|
+
author: {
|
|
31586
|
+
name: "Daniel Sieradski",
|
|
31587
|
+
email: "daniel@self.agency",
|
|
31588
|
+
url: "https://self.agency"
|
|
31589
|
+
},
|
|
31590
|
+
repository: {
|
|
31591
|
+
type: "git",
|
|
31592
|
+
url: "git+https://github.com/selfagency/beans-mcp.git"
|
|
31593
|
+
},
|
|
31594
|
+
bin: {
|
|
31595
|
+
"beans-mcp": "dist/beans-mcp-server.cjs"
|
|
31596
|
+
},
|
|
31597
|
+
files: [
|
|
31598
|
+
"dist",
|
|
31599
|
+
"skills",
|
|
31600
|
+
"README.md",
|
|
31601
|
+
"LICENSE.txt"
|
|
31602
|
+
],
|
|
31603
|
+
type: "module",
|
|
31604
|
+
main: "./dist/index.cjs",
|
|
31605
|
+
module: "./dist/index.js",
|
|
31606
|
+
types: "./dist/index.d.ts",
|
|
31607
|
+
exports: {
|
|
31608
|
+
".": {
|
|
31609
|
+
types: "./dist/index.d.ts",
|
|
31610
|
+
import: "./dist/index.js",
|
|
31611
|
+
require: "./dist/index.cjs"
|
|
31612
|
+
}
|
|
31613
|
+
},
|
|
31614
|
+
scripts: {
|
|
31615
|
+
build: "tsup",
|
|
31616
|
+
"docs:dev": "vitepress dev docs",
|
|
31617
|
+
"docs:build": "vitepress build docs",
|
|
31618
|
+
"docs:preview": "vitepress preview docs",
|
|
31619
|
+
format: "oxfmt",
|
|
31620
|
+
"lint:fix": "oxlint --fix",
|
|
31621
|
+
lint: "oxlint",
|
|
31622
|
+
postbuild: "node ./scripts/write-dist-package.js",
|
|
31623
|
+
prepare: "husky",
|
|
31624
|
+
release: "zx ./scripts/release.js",
|
|
31625
|
+
"test:coverage": "vitest run --coverage",
|
|
31626
|
+
"test:watch": "vitest",
|
|
31627
|
+
test: "vitest run",
|
|
31628
|
+
"type-check": "tsc --noEmit"
|
|
31629
|
+
},
|
|
31630
|
+
devDependencies: {
|
|
31631
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
31632
|
+
"@octokit/rest": "^22.0.1",
|
|
31633
|
+
"@types/node": "25.6.0",
|
|
31634
|
+
"@vitest/coverage-v8": "^4.1.4",
|
|
31635
|
+
"@vitest/ui": "4.1.4",
|
|
31636
|
+
husky: "^9.1.7",
|
|
31637
|
+
"lint-staged": "^16.4.0",
|
|
31638
|
+
ora: "^9.3.0",
|
|
31639
|
+
oxfmt: "^0.45.0",
|
|
31640
|
+
oxlint: "^1.60.0",
|
|
31641
|
+
"oxlint-tsgolint": "^0.21.1",
|
|
31642
|
+
tsup: "8.5.1",
|
|
31643
|
+
typescript: "6.0.3",
|
|
31644
|
+
vitepress: "^1.6.4",
|
|
31645
|
+
vitest: "4.1.4",
|
|
31646
|
+
zod: "4.3.6",
|
|
31647
|
+
zx: "^8.8.5"
|
|
31648
|
+
},
|
|
31649
|
+
"lint-staged": {
|
|
31650
|
+
"src/**/*.ts": [
|
|
31651
|
+
"pnpm run lint:fix",
|
|
31652
|
+
"pnpm run format"
|
|
31653
|
+
]
|
|
31654
|
+
},
|
|
31655
|
+
engines: {
|
|
31656
|
+
node: ">=18"
|
|
31657
|
+
},
|
|
31658
|
+
mcpName: "io.github.selfagency/beans-mcp"
|
|
31659
|
+
};
|
|
31660
|
+
|
|
31156
31661
|
// src/internal/queryHelpers.ts
|
|
31157
31662
|
function sortBeansInternal(beans, mode) {
|
|
31158
31663
|
const sorted = [...beans];
|
|
@@ -31313,94 +31818,10 @@ var MAX_PATH_LENGTH = 1024;
|
|
|
31313
31818
|
|
|
31314
31819
|
// src/server/BeansMcpServer.ts
|
|
31315
31820
|
init_utils();
|
|
31316
|
-
|
|
31317
|
-
// package.json
|
|
31318
|
-
var package_default = {
|
|
31319
|
-
name: "@selfagency/beans-mcp",
|
|
31320
|
-
version: "0.4.2",
|
|
31321
|
-
private: false,
|
|
31322
|
-
description: "MCP (Model Context Protocol) server for Beans issue tracker",
|
|
31323
|
-
author: {
|
|
31324
|
-
name: "Daniel Sieradski",
|
|
31325
|
-
email: "daniel@self.agency",
|
|
31326
|
-
url: "https://self.agency"
|
|
31327
|
-
},
|
|
31328
|
-
homepage: "https://github.com/hmans/beans",
|
|
31329
|
-
bugs: {
|
|
31330
|
-
url: "https://github.com/selfagency/beans-mcp/issues"
|
|
31331
|
-
},
|
|
31332
|
-
repository: {
|
|
31333
|
-
type: "git",
|
|
31334
|
-
url: "git+https://github.com/selfagency/beans-mcp.git"
|
|
31335
|
-
},
|
|
31336
|
-
mcpName: "io.github.selfagency/beans-mcp",
|
|
31337
|
-
keywords: [
|
|
31338
|
-
"beans",
|
|
31339
|
-
"mcp",
|
|
31340
|
-
"model-context-protocol",
|
|
31341
|
-
"issue-tracker",
|
|
31342
|
-
"ai"
|
|
31343
|
-
],
|
|
31344
|
-
license: "MIT",
|
|
31345
|
-
type: "module",
|
|
31346
|
-
exports: {
|
|
31347
|
-
".": {
|
|
31348
|
-
types: "./dist/index.d.ts",
|
|
31349
|
-
import: "./dist/index.js",
|
|
31350
|
-
require: "./dist/index.cjs"
|
|
31351
|
-
}
|
|
31352
|
-
},
|
|
31353
|
-
main: "./dist/index.cjs",
|
|
31354
|
-
module: "./dist/index.js",
|
|
31355
|
-
types: "./dist/index.d.ts",
|
|
31356
|
-
bin: {
|
|
31357
|
-
"beans-mcp": "dist/beans-mcp-server.cjs"
|
|
31358
|
-
},
|
|
31359
|
-
scripts: {
|
|
31360
|
-
build: "tsup",
|
|
31361
|
-
format: "oxfmt",
|
|
31362
|
-
"lint:fix": "oxlint --fix",
|
|
31363
|
-
lint: "oxlint",
|
|
31364
|
-
postbuild: "node ./scripts/write-dist-package.js",
|
|
31365
|
-
prepare: "husky",
|
|
31366
|
-
release: "zx ./scripts/release.js",
|
|
31367
|
-
"test:coverage": "vitest run --coverage",
|
|
31368
|
-
"test:watch": "vitest",
|
|
31369
|
-
test: "vitest run",
|
|
31370
|
-
"type-check": "tsc --noEmit"
|
|
31371
|
-
},
|
|
31372
|
-
devDependencies: {
|
|
31373
|
-
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
31374
|
-
"@octokit/rest": "^22.0.1",
|
|
31375
|
-
"@types/node": "25.5.0",
|
|
31376
|
-
"@vitest/coverage-v8": "^4.1.0",
|
|
31377
|
-
"@vitest/ui": "4.1.0",
|
|
31378
|
-
husky: "^9.1.7",
|
|
31379
|
-
"lint-staged": "^16.3.3",
|
|
31380
|
-
ora: "^9.3.0",
|
|
31381
|
-
oxfmt: "^0.40.0",
|
|
31382
|
-
oxlint: "^1.55.0",
|
|
31383
|
-
"oxlint-tsgolint": "^0.16.0",
|
|
31384
|
-
tsup: "8.5.1",
|
|
31385
|
-
typescript: "^5.9.3",
|
|
31386
|
-
vitest: "4.1.0",
|
|
31387
|
-
zod: "4.3.6",
|
|
31388
|
-
zx: "^8.8.5"
|
|
31389
|
-
},
|
|
31390
|
-
engines: {
|
|
31391
|
-
node: ">=18"
|
|
31392
|
-
},
|
|
31393
|
-
"lint-staged": {
|
|
31394
|
-
"src/**/*.ts": [
|
|
31395
|
-
"pnpm run lint:fix",
|
|
31396
|
-
"pnpm run format"
|
|
31397
|
-
]
|
|
31398
|
-
}
|
|
31399
|
-
};
|
|
31400
|
-
|
|
31401
|
-
// src/server/BeansMcpServer.ts
|
|
31402
31821
|
var execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process2.execFile);
|
|
31403
31822
|
var PACKAGE_VERSION = package_default.version ?? "0.0.0-dev";
|
|
31823
|
+
var CLOSED_STATUSES = /* @__PURE__ */ new Set(["completed", "scrapped"]);
|
|
31824
|
+
var BEAN_ID_HINT = "Missing required field `beanId`. Did you mean `beanId`?";
|
|
31404
31825
|
function getSafeCliEnv(env) {
|
|
31405
31826
|
const whitelist = ["PATH", "HOME", "USER", "LANG", "LC_ALL", "LC_CTYPE", "SHELL"];
|
|
31406
31827
|
const safeEnv = {};
|
|
@@ -31421,7 +31842,8 @@ function extractVersionFromOutput(output) {
|
|
|
31421
31842
|
if (!trimmed) {
|
|
31422
31843
|
return null;
|
|
31423
31844
|
}
|
|
31424
|
-
const
|
|
31845
|
+
const versionRegex = /(?:^|[^\d])v?(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)/;
|
|
31846
|
+
const match = versionRegex.exec(trimmed);
|
|
31425
31847
|
return match?.[1] ?? null;
|
|
31426
31848
|
}
|
|
31427
31849
|
async function detectBeansCliVersion(cliPath, workspaceRoot) {
|
|
@@ -31438,10 +31860,10 @@ ${stderr}`);
|
|
|
31438
31860
|
return null;
|
|
31439
31861
|
}
|
|
31440
31862
|
}
|
|
31441
|
-
async function getBeanById(backend, beanId) {
|
|
31863
|
+
async function getBeanById(backend, beanId, beans) {
|
|
31442
31864
|
try {
|
|
31443
|
-
const
|
|
31444
|
-
const found =
|
|
31865
|
+
const allBeans = beans ?? await backend.list();
|
|
31866
|
+
const found = allBeans.find((b) => b.id === beanId);
|
|
31445
31867
|
if (!found) {
|
|
31446
31868
|
throw new Error(`Bean not found: ${beanId}`);
|
|
31447
31869
|
}
|
|
@@ -31450,12 +31872,111 @@ async function getBeanById(backend, beanId) {
|
|
|
31450
31872
|
throw new Error(`Failed to fetch bean ${beanId}: ${error48.message}`);
|
|
31451
31873
|
}
|
|
31452
31874
|
}
|
|
31875
|
+
function collectDescendantBeans(beans, rootBeanId) {
|
|
31876
|
+
const byParent = /* @__PURE__ */ new Map();
|
|
31877
|
+
const byId = new Map(beans.map((bean) => [bean.id, bean]));
|
|
31878
|
+
for (const bean of beans) {
|
|
31879
|
+
if (!bean.parentId) {
|
|
31880
|
+
continue;
|
|
31881
|
+
}
|
|
31882
|
+
const children = byParent.get(bean.parentId) ?? [];
|
|
31883
|
+
children.push(bean.id);
|
|
31884
|
+
byParent.set(bean.parentId, children);
|
|
31885
|
+
}
|
|
31886
|
+
const queue = [...byParent.get(rootBeanId) ?? []];
|
|
31887
|
+
const visited = /* @__PURE__ */ new Set();
|
|
31888
|
+
const descendants = [];
|
|
31889
|
+
while (queue.length > 0) {
|
|
31890
|
+
const currentId = queue.shift();
|
|
31891
|
+
if (!currentId || visited.has(currentId)) {
|
|
31892
|
+
continue;
|
|
31893
|
+
}
|
|
31894
|
+
visited.add(currentId);
|
|
31895
|
+
const currentBean = byId.get(currentId);
|
|
31896
|
+
if (!currentBean) {
|
|
31897
|
+
continue;
|
|
31898
|
+
}
|
|
31899
|
+
descendants.push(currentBean);
|
|
31900
|
+
const children = byParent.get(currentId);
|
|
31901
|
+
if (children && children.length > 0) {
|
|
31902
|
+
queue.push(...children);
|
|
31903
|
+
}
|
|
31904
|
+
}
|
|
31905
|
+
return descendants;
|
|
31906
|
+
}
|
|
31907
|
+
async function cascadeStatusToDescendants(backend, rootBeanId, targetStatus, options) {
|
|
31908
|
+
const beans = options?.beans ?? await backend.list();
|
|
31909
|
+
const descendants = collectDescendantBeans(beans, rootBeanId);
|
|
31910
|
+
const updatedBeanIds = [];
|
|
31911
|
+
const skippedBeanIds = [];
|
|
31912
|
+
const errors = [];
|
|
31913
|
+
const toUpdate = [];
|
|
31914
|
+
for (const bean of descendants) {
|
|
31915
|
+
if (options?.onlyCurrentStatuses && !options.onlyCurrentStatuses.has(bean.status)) {
|
|
31916
|
+
skippedBeanIds.push(bean.id);
|
|
31917
|
+
continue;
|
|
31918
|
+
}
|
|
31919
|
+
toUpdate.push(bean);
|
|
31920
|
+
}
|
|
31921
|
+
const settled = await Promise.allSettled(
|
|
31922
|
+
toUpdate.map(async (bean) => backend.update(bean.id, { status: targetStatus }))
|
|
31923
|
+
);
|
|
31924
|
+
settled.forEach((result, index) => {
|
|
31925
|
+
const bean = toUpdate[index];
|
|
31926
|
+
if (!bean) {
|
|
31927
|
+
return;
|
|
31928
|
+
}
|
|
31929
|
+
if (result.status === "fulfilled") {
|
|
31930
|
+
updatedBeanIds.push(bean.id);
|
|
31931
|
+
return;
|
|
31932
|
+
}
|
|
31933
|
+
errors.push({
|
|
31934
|
+
beanId: bean.id,
|
|
31935
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
31936
|
+
});
|
|
31937
|
+
});
|
|
31938
|
+
return {
|
|
31939
|
+
totalDescendants: descendants.length,
|
|
31940
|
+
updatedBeanIds,
|
|
31941
|
+
skippedBeanIds,
|
|
31942
|
+
errors
|
|
31943
|
+
};
|
|
31944
|
+
}
|
|
31945
|
+
function completeMarkdownTasks(body) {
|
|
31946
|
+
const lines = body.split(/\r?\n/);
|
|
31947
|
+
let totalTaskCount = 0;
|
|
31948
|
+
let updatedTaskCount = 0;
|
|
31949
|
+
const taskLinePattern = /^\s*(?:[-*+]|\d+\.)\s+\[[ xX]\]/;
|
|
31950
|
+
const uncheckedTaskLinePattern = /^(\s*(?:[-*+]|\d+\.)\s+\[)\s(\].*)$/;
|
|
31951
|
+
const nextLines = lines.map((line) => {
|
|
31952
|
+
if (!taskLinePattern.test(line)) {
|
|
31953
|
+
return line;
|
|
31954
|
+
}
|
|
31955
|
+
totalTaskCount += 1;
|
|
31956
|
+
const uncheckedMatch = uncheckedTaskLinePattern.exec(line);
|
|
31957
|
+
if (!uncheckedMatch) {
|
|
31958
|
+
return line;
|
|
31959
|
+
}
|
|
31960
|
+
updatedTaskCount += 1;
|
|
31961
|
+
return `${uncheckedMatch[1]}x${uncheckedMatch[2]}`;
|
|
31962
|
+
});
|
|
31963
|
+
const nextBody = nextLines.join("\n");
|
|
31964
|
+
return { nextBody, totalTaskCount, updatedTaskCount };
|
|
31965
|
+
}
|
|
31453
31966
|
function initHandler(backend) {
|
|
31454
31967
|
return async ({ prefix }) => {
|
|
31455
31968
|
const result = await backend.init(prefix);
|
|
31456
31969
|
return makeTextAndStructured(result);
|
|
31457
31970
|
};
|
|
31458
31971
|
}
|
|
31972
|
+
function archiveHandler(backend) {
|
|
31973
|
+
return async () => {
|
|
31974
|
+
if (typeof backend.archive !== "function") {
|
|
31975
|
+
throw new TypeError("Archive is not supported by the current backend");
|
|
31976
|
+
}
|
|
31977
|
+
return makeTextAndStructured(await backend.archive());
|
|
31978
|
+
};
|
|
31979
|
+
}
|
|
31459
31980
|
function viewHandler(backend) {
|
|
31460
31981
|
return async ({ beanId, beanIds }) => {
|
|
31461
31982
|
const ids = Array.isArray(beanIds) && beanIds.length > 0 ? beanIds : beanId ? [beanId] : [];
|
|
@@ -31470,7 +31991,12 @@ function viewHandler(backend) {
|
|
|
31470
31991
|
const byId = new Map(beans.map((b) => [b.id, b]));
|
|
31471
31992
|
const found = ids.map((id) => byId.get(id)).filter(Boolean);
|
|
31472
31993
|
const missingBeanIds = ids.filter((id) => !byId.has(id));
|
|
31473
|
-
return makeTextAndStructured({
|
|
31994
|
+
return makeTextAndStructured({
|
|
31995
|
+
beans: found,
|
|
31996
|
+
missingBeanIds,
|
|
31997
|
+
count: found.length,
|
|
31998
|
+
requestedCount: ids.length
|
|
31999
|
+
});
|
|
31474
32000
|
};
|
|
31475
32001
|
}
|
|
31476
32002
|
async function checkVersionCompatibility(cliPath, workspaceRoot, detector) {
|
|
@@ -31488,7 +32014,14 @@ async function checkVersionCompatibility(cliPath, workspaceRoot, detector) {
|
|
|
31488
32014
|
}
|
|
31489
32015
|
}
|
|
31490
32016
|
function createHandler(backend) {
|
|
31491
|
-
return async (input) =>
|
|
32017
|
+
return async (input) => {
|
|
32018
|
+
const bean = await backend.create(input);
|
|
32019
|
+
const warnings = input.description !== void 0 ? ["`description` is deprecated; use `body` instead."] : void 0;
|
|
32020
|
+
return makeTextAndStructured({
|
|
32021
|
+
bean,
|
|
32022
|
+
...warnings ? { warnings } : {}
|
|
32023
|
+
});
|
|
32024
|
+
};
|
|
31492
32025
|
}
|
|
31493
32026
|
function editHandler(backend) {
|
|
31494
32027
|
return async ({
|
|
@@ -31502,18 +32035,30 @@ function reopenHandler(backend) {
|
|
|
31502
32035
|
requiredCurrentStatus,
|
|
31503
32036
|
targetStatus
|
|
31504
32037
|
}) => {
|
|
31505
|
-
const
|
|
31506
|
-
|
|
31507
|
-
|
|
32038
|
+
const beans = await backend.list();
|
|
32039
|
+
const bean = await getBeanById(backend, beanId, beans);
|
|
32040
|
+
if (bean.status === requiredCurrentStatus) {
|
|
32041
|
+
const updatedParentBean = await backend.update(beanId, { status: targetStatus });
|
|
32042
|
+
const cascade = await cascadeStatusToDescendants(backend, beanId, targetStatus, {
|
|
32043
|
+
onlyCurrentStatuses: CLOSED_STATUSES,
|
|
32044
|
+
beans
|
|
32045
|
+
});
|
|
32046
|
+
return makeTextAndStructured({
|
|
32047
|
+
bean: updatedParentBean,
|
|
32048
|
+
cascade: {
|
|
32049
|
+
totalDescendants: cascade.totalDescendants,
|
|
32050
|
+
updatedBeanIds: cascade.updatedBeanIds,
|
|
32051
|
+
skippedBeanIds: cascade.skippedBeanIds,
|
|
32052
|
+
errors: cascade.errors
|
|
32053
|
+
}
|
|
32054
|
+
});
|
|
31508
32055
|
}
|
|
31509
|
-
|
|
31510
|
-
bean: await backend.update(beanId, { status: targetStatus })
|
|
31511
|
-
});
|
|
32056
|
+
throw new Error(`Bean ${beanId} is not ${requiredCurrentStatus}`);
|
|
31512
32057
|
};
|
|
31513
32058
|
}
|
|
31514
32059
|
function updateHandler(backend) {
|
|
31515
|
-
return async (input) =>
|
|
31516
|
-
|
|
32060
|
+
return async (input) => {
|
|
32061
|
+
const updatedBean = await backend.update(input.beanId, {
|
|
31517
32062
|
status: input.status,
|
|
31518
32063
|
type: input.type,
|
|
31519
32064
|
priority: input.priority,
|
|
@@ -31525,8 +32070,37 @@ function updateHandler(backend) {
|
|
|
31525
32070
|
bodyAppend: input.bodyAppend,
|
|
31526
32071
|
bodyReplace: input.bodyReplace,
|
|
31527
32072
|
ifMatch: input.ifMatch
|
|
31528
|
-
})
|
|
31529
|
-
|
|
32073
|
+
});
|
|
32074
|
+
const closeStatus = input.status;
|
|
32075
|
+
const shouldCascadeClose = Boolean(closeStatus && CLOSED_STATUSES.has(closeStatus));
|
|
32076
|
+
const cascade = shouldCascadeClose ? await cascadeStatusToDescendants(backend, input.beanId, closeStatus, {
|
|
32077
|
+
beans: await backend.list()
|
|
32078
|
+
}) : null;
|
|
32079
|
+
return makeTextAndStructured({
|
|
32080
|
+
bean: updatedBean,
|
|
32081
|
+
...cascade ? {
|
|
32082
|
+
cascade: {
|
|
32083
|
+
totalDescendants: cascade.totalDescendants,
|
|
32084
|
+
updatedBeanIds: cascade.updatedBeanIds,
|
|
32085
|
+
skippedBeanIds: cascade.skippedBeanIds,
|
|
32086
|
+
errors: cascade.errors
|
|
32087
|
+
}
|
|
32088
|
+
} : {}
|
|
32089
|
+
});
|
|
32090
|
+
};
|
|
32091
|
+
}
|
|
32092
|
+
function completeTasksHandler(backend) {
|
|
32093
|
+
return async ({ beanId }) => {
|
|
32094
|
+
const bean = await getBeanById(backend, beanId);
|
|
32095
|
+
const { nextBody, totalTaskCount, updatedTaskCount } = completeMarkdownTasks(bean.body || "");
|
|
32096
|
+
const updatedBean = updatedTaskCount > 0 ? await backend.update(beanId, { body: nextBody }) : bean;
|
|
32097
|
+
return makeTextAndStructured({
|
|
32098
|
+
bean: updatedBean,
|
|
32099
|
+
totalTaskCount,
|
|
32100
|
+
updatedTaskCount,
|
|
32101
|
+
unchangedTaskCount: totalTaskCount - updatedTaskCount
|
|
32102
|
+
});
|
|
32103
|
+
};
|
|
31530
32104
|
}
|
|
31531
32105
|
function deleteHandler(backend) {
|
|
31532
32106
|
return async ({ beanId, beanIds, force }) => {
|
|
@@ -31562,7 +32136,11 @@ function deleteHandler(backend) {
|
|
|
31562
32136
|
await backend.delete(id);
|
|
31563
32137
|
results.push({ beanId: id, deleted: true });
|
|
31564
32138
|
} catch (error48) {
|
|
31565
|
-
results.push({
|
|
32139
|
+
results.push({
|
|
32140
|
+
beanId: id,
|
|
32141
|
+
deleted: false,
|
|
32142
|
+
error: error48.message
|
|
32143
|
+
});
|
|
31566
32144
|
}
|
|
31567
32145
|
}
|
|
31568
32146
|
return makeTextAndStructured({
|
|
@@ -31573,15 +32151,53 @@ function deleteHandler(backend) {
|
|
|
31573
32151
|
});
|
|
31574
32152
|
};
|
|
31575
32153
|
}
|
|
32154
|
+
function bulkCreateHandler(backend) {
|
|
32155
|
+
return async (input) => {
|
|
32156
|
+
const results = await backend.bulkCreate(input.beans, input.parent);
|
|
32157
|
+
const deprecatedDescriptionCount = input.beans.filter((bean) => bean.description !== void 0).length;
|
|
32158
|
+
return makeTextAndStructured({
|
|
32159
|
+
results,
|
|
32160
|
+
requestedCount: input.beans.length,
|
|
32161
|
+
successCount: results.filter((r) => r.bean).length,
|
|
32162
|
+
failedCount: results.filter((r) => r.error).length,
|
|
32163
|
+
...deprecatedDescriptionCount > 0 ? {
|
|
32164
|
+
warnings: [
|
|
32165
|
+
`Found ${deprecatedDescriptionCount} bean(s) using deprecated field \`description\`; use \`body\` instead.`
|
|
32166
|
+
]
|
|
32167
|
+
} : {}
|
|
32168
|
+
});
|
|
32169
|
+
};
|
|
32170
|
+
}
|
|
32171
|
+
function bulkUpdateHandler(backend) {
|
|
32172
|
+
return async (input) => {
|
|
32173
|
+
const results = await backend.bulkUpdate(input.beans, input.parent);
|
|
32174
|
+
return makeTextAndStructured({
|
|
32175
|
+
results,
|
|
32176
|
+
requestedCount: input.beans.length,
|
|
32177
|
+
successCount: results.filter((r) => r.bean).length,
|
|
32178
|
+
failedCount: results.filter((r) => r.error).length
|
|
32179
|
+
});
|
|
32180
|
+
};
|
|
32181
|
+
}
|
|
31576
32182
|
function queryHandler(backend) {
|
|
31577
|
-
return async (opts) =>
|
|
32183
|
+
return async (opts) => {
|
|
32184
|
+
if (opts.operation === "graphql") {
|
|
32185
|
+
if (typeof backend.queryGraphql !== "function") {
|
|
32186
|
+
throw new TypeError("GraphQL passthrough is not supported by the current backend");
|
|
32187
|
+
}
|
|
32188
|
+
const result = await backend.queryGraphql(opts.graphql || "", opts.variables);
|
|
32189
|
+
return makeTextAndStructured({ data: result.data, errors: result.errors ?? [] });
|
|
32190
|
+
}
|
|
32191
|
+
return handleQueryOperation(backend, opts);
|
|
32192
|
+
};
|
|
31578
32193
|
}
|
|
31579
32194
|
function beanFileHandler(backend) {
|
|
31580
32195
|
return async ({
|
|
31581
32196
|
operation,
|
|
31582
32197
|
path,
|
|
31583
32198
|
content,
|
|
31584
|
-
overwrite
|
|
32199
|
+
overwrite,
|
|
32200
|
+
fields
|
|
31585
32201
|
}) => {
|
|
31586
32202
|
if (operation === "read") {
|
|
31587
32203
|
return makeTextAndStructured(await backend.readBeanFile(path));
|
|
@@ -31592,6 +32208,9 @@ function beanFileHandler(backend) {
|
|
|
31592
32208
|
if (operation === "create") {
|
|
31593
32209
|
return makeTextAndStructured(await backend.createBeanFile(path, content || "", { overwrite }));
|
|
31594
32210
|
}
|
|
32211
|
+
if (operation === "update_frontmatter") {
|
|
32212
|
+
return makeTextAndStructured(await backend.updateBeanFrontmatter(path, fields || {}));
|
|
32213
|
+
}
|
|
31595
32214
|
if (operation === "delete") {
|
|
31596
32215
|
return makeTextAndStructured(await backend.deleteBeanFile(path));
|
|
31597
32216
|
}
|
|
@@ -31626,6 +32245,21 @@ function registerTools(server, backend) {
|
|
|
31626
32245
|
},
|
|
31627
32246
|
initHandler(backend)
|
|
31628
32247
|
);
|
|
32248
|
+
server.registerTool(
|
|
32249
|
+
"beans_archive",
|
|
32250
|
+
{
|
|
32251
|
+
title: "Archive Beans",
|
|
32252
|
+
description: "Archive completed or scrapped beans, equivalent to the beans CLI archive command.",
|
|
32253
|
+
inputSchema: external_exports3.object({}),
|
|
32254
|
+
annotations: {
|
|
32255
|
+
readOnlyHint: false,
|
|
32256
|
+
destructiveHint: false,
|
|
32257
|
+
idempotentHint: false,
|
|
32258
|
+
openWorldHint: false
|
|
32259
|
+
}
|
|
32260
|
+
},
|
|
32261
|
+
archiveHandler(backend)
|
|
32262
|
+
);
|
|
31629
32263
|
server.registerTool(
|
|
31630
32264
|
"beans_view",
|
|
31631
32265
|
{
|
|
@@ -31635,7 +32269,7 @@ function registerTools(server, backend) {
|
|
|
31635
32269
|
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
31636
32270
|
beanIds: external_exports3.array(external_exports3.string().min(1).max(MAX_ID_LENGTH)).optional()
|
|
31637
32271
|
}).refine((input) => Boolean(input.beanId) || Array.isArray(input.beanIds) && input.beanIds.length > 0, {
|
|
31638
|
-
message:
|
|
32272
|
+
message: `Either beanId or beanIds must be provided. ${BEAN_ID_HINT}`
|
|
31639
32273
|
}),
|
|
31640
32274
|
annotations: {
|
|
31641
32275
|
readOnlyHint: true,
|
|
@@ -31656,7 +32290,8 @@ function registerTools(server, backend) {
|
|
|
31656
32290
|
type: external_exports3.string().min(1).max(MAX_METADATA_LENGTH),
|
|
31657
32291
|
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31658
32292
|
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31659
|
-
|
|
32293
|
+
body: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional().describe("Body markdown content"),
|
|
32294
|
+
description: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional().describe("Deprecated alias for body"),
|
|
31660
32295
|
parent: external_exports3.string().max(MAX_ID_LENGTH).optional()
|
|
31661
32296
|
}),
|
|
31662
32297
|
annotations: {
|
|
@@ -31674,7 +32309,7 @@ function registerTools(server, backend) {
|
|
|
31674
32309
|
title: "Edit Bean Metadata",
|
|
31675
32310
|
description: "Update bean metadata fields (status/type/priority/parent/blocking).",
|
|
31676
32311
|
inputSchema: external_exports3.object({
|
|
31677
|
-
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH),
|
|
32312
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
31678
32313
|
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31679
32314
|
type: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31680
32315
|
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
@@ -31682,7 +32317,11 @@ function registerTools(server, backend) {
|
|
|
31682
32317
|
clearParent: external_exports3.boolean().optional(),
|
|
31683
32318
|
blocking: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).optional(),
|
|
31684
32319
|
blockedBy: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).optional()
|
|
31685
|
-
}),
|
|
32320
|
+
}).superRefine((input, ctx) => {
|
|
32321
|
+
if (!input.beanId) {
|
|
32322
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["beanId"], message: BEAN_ID_HINT });
|
|
32323
|
+
}
|
|
32324
|
+
}).transform((input) => ({ ...input, beanId: input.beanId })),
|
|
31686
32325
|
annotations: {
|
|
31687
32326
|
readOnlyHint: false,
|
|
31688
32327
|
destructiveHint: false,
|
|
@@ -31698,10 +32337,14 @@ function registerTools(server, backend) {
|
|
|
31698
32337
|
title: "Reopen Bean",
|
|
31699
32338
|
description: "Reopen a completed or scrapped bean into a non-closed status.",
|
|
31700
32339
|
inputSchema: external_exports3.object({
|
|
31701
|
-
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH),
|
|
32340
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
31702
32341
|
requiredCurrentStatus: external_exports3.enum(["completed", "scrapped"]),
|
|
31703
32342
|
targetStatus: external_exports3.string().max(MAX_METADATA_LENGTH).default("todo")
|
|
31704
|
-
}),
|
|
32343
|
+
}).superRefine((input, ctx) => {
|
|
32344
|
+
if (!input.beanId) {
|
|
32345
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["beanId"], message: BEAN_ID_HINT });
|
|
32346
|
+
}
|
|
32347
|
+
}).transform((input) => ({ ...input, beanId: input.beanId })),
|
|
31705
32348
|
annotations: {
|
|
31706
32349
|
readOnlyHint: false,
|
|
31707
32350
|
destructiveHint: false,
|
|
@@ -31717,7 +32360,7 @@ function registerTools(server, backend) {
|
|
|
31717
32360
|
title: "Update Bean",
|
|
31718
32361
|
description: "Update bean metadata fields (status/type/priority/parent/blocking). Consolidated replacement for per-field update tools.",
|
|
31719
32362
|
inputSchema: external_exports3.object({
|
|
31720
|
-
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH),
|
|
32363
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
31721
32364
|
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31722
32365
|
type: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31723
32366
|
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
@@ -31734,12 +32377,16 @@ function registerTools(server, backend) {
|
|
|
31734
32377
|
})
|
|
31735
32378
|
).optional(),
|
|
31736
32379
|
ifMatch: external_exports3.string().max(MAX_METADATA_LENGTH).optional()
|
|
32380
|
+
}).superRefine((input, ctx) => {
|
|
32381
|
+
if (!input.beanId) {
|
|
32382
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["beanId"], message: BEAN_ID_HINT });
|
|
32383
|
+
}
|
|
31737
32384
|
}).refine(
|
|
31738
32385
|
(input) => !(input.body !== void 0 && (input.bodyAppend !== void 0 || input.bodyReplace !== void 0)),
|
|
31739
32386
|
{
|
|
31740
32387
|
message: "body cannot be combined with bodyAppend/bodyReplace"
|
|
31741
32388
|
}
|
|
31742
|
-
),
|
|
32389
|
+
).transform((input) => ({ ...input, beanId: input.beanId })),
|
|
31743
32390
|
annotations: {
|
|
31744
32391
|
readOnlyHint: false,
|
|
31745
32392
|
destructiveHint: false,
|
|
@@ -31759,7 +32406,7 @@ function registerTools(server, backend) {
|
|
|
31759
32406
|
beanIds: external_exports3.array(external_exports3.string().min(1).max(MAX_ID_LENGTH)).optional(),
|
|
31760
32407
|
force: external_exports3.boolean().default(false)
|
|
31761
32408
|
}).refine((input) => Boolean(input.beanId) || Array.isArray(input.beanIds) && input.beanIds.length > 0, {
|
|
31762
|
-
message:
|
|
32409
|
+
message: `Either beanId or beanIds must be provided. ${BEAN_ID_HINT}`
|
|
31763
32410
|
}),
|
|
31764
32411
|
annotations: {
|
|
31765
32412
|
readOnlyHint: false,
|
|
@@ -31770,25 +32417,122 @@ function registerTools(server, backend) {
|
|
|
31770
32417
|
},
|
|
31771
32418
|
deleteHandler(backend)
|
|
31772
32419
|
);
|
|
32420
|
+
const beanCreateItemSchema = external_exports3.object({
|
|
32421
|
+
title: external_exports3.string().min(1).max(MAX_TITLE_LENGTH),
|
|
32422
|
+
type: external_exports3.string().min(1).max(MAX_METADATA_LENGTH),
|
|
32423
|
+
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32424
|
+
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32425
|
+
body: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional().describe("Body markdown content"),
|
|
32426
|
+
description: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional().describe("Deprecated alias for body"),
|
|
32427
|
+
parent: external_exports3.string().max(MAX_ID_LENGTH).optional().describe("Override the top-level parent for this item")
|
|
32428
|
+
});
|
|
32429
|
+
server.registerTool(
|
|
32430
|
+
"beans_bulk_create",
|
|
32431
|
+
{
|
|
32432
|
+
title: "Bulk Create Beans",
|
|
32433
|
+
description: "Create multiple beans in one call. Optionally assign all of them (or a subset) to a shared parent.",
|
|
32434
|
+
inputSchema: external_exports3.object({
|
|
32435
|
+
beans: external_exports3.array(beanCreateItemSchema).min(1),
|
|
32436
|
+
parent: external_exports3.string().max(MAX_ID_LENGTH).optional().describe("Default parent ID applied to any bean that does not specify its own parent")
|
|
32437
|
+
}),
|
|
32438
|
+
annotations: {
|
|
32439
|
+
readOnlyHint: false,
|
|
32440
|
+
destructiveHint: false,
|
|
32441
|
+
idempotentHint: false,
|
|
32442
|
+
openWorldHint: false
|
|
32443
|
+
}
|
|
32444
|
+
},
|
|
32445
|
+
bulkCreateHandler(backend)
|
|
32446
|
+
);
|
|
32447
|
+
const beanUpdateItemSchema = external_exports3.object({
|
|
32448
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
32449
|
+
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32450
|
+
type: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32451
|
+
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32452
|
+
parent: external_exports3.string().max(MAX_ID_LENGTH).optional().describe("Override the top-level parent for this item"),
|
|
32453
|
+
clearParent: external_exports3.boolean().optional(),
|
|
32454
|
+
blocking: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).optional(),
|
|
32455
|
+
blockedBy: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).optional(),
|
|
32456
|
+
body: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
32457
|
+
bodyAppend: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
32458
|
+
bodyReplace: external_exports3.array(external_exports3.object({ old: external_exports3.string().max(MAX_DESCRIPTION_LENGTH), new: external_exports3.string().max(MAX_DESCRIPTION_LENGTH) })).optional(),
|
|
32459
|
+
ifMatch: external_exports3.string().max(MAX_METADATA_LENGTH).optional()
|
|
32460
|
+
}).superRefine((input, ctx) => {
|
|
32461
|
+
if (!input.beanId) {
|
|
32462
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["beanId"], message: BEAN_ID_HINT });
|
|
32463
|
+
}
|
|
32464
|
+
}).refine(
|
|
32465
|
+
(input) => !(input.body !== void 0 && (input.bodyAppend !== void 0 || input.bodyReplace !== void 0)),
|
|
32466
|
+
{ message: "body cannot be combined with bodyAppend/bodyReplace" }
|
|
32467
|
+
).transform((input) => ({ ...input, beanId: input.beanId }));
|
|
32468
|
+
server.registerTool(
|
|
32469
|
+
"beans_bulk_update",
|
|
32470
|
+
{
|
|
32471
|
+
title: "Bulk Update Beans",
|
|
32472
|
+
description: "Update multiple beans in one call. Optionally assign all of them (or a subset) to a shared parent.",
|
|
32473
|
+
inputSchema: external_exports3.object({
|
|
32474
|
+
beans: external_exports3.array(beanUpdateItemSchema).min(1),
|
|
32475
|
+
parent: external_exports3.string().max(MAX_ID_LENGTH).optional().describe("Default parent ID applied to any bean that does not specify its own parent")
|
|
32476
|
+
}),
|
|
32477
|
+
annotations: {
|
|
32478
|
+
readOnlyHint: false,
|
|
32479
|
+
destructiveHint: false,
|
|
32480
|
+
idempotentHint: false,
|
|
32481
|
+
openWorldHint: false
|
|
32482
|
+
}
|
|
32483
|
+
},
|
|
32484
|
+
bulkUpdateHandler(backend)
|
|
32485
|
+
);
|
|
32486
|
+
server.registerTool(
|
|
32487
|
+
"beans_complete_tasks",
|
|
32488
|
+
{
|
|
32489
|
+
title: "Complete Markdown Tasks",
|
|
32490
|
+
description: "Mark all markdown checklist tasks within a bean as completed.",
|
|
32491
|
+
inputSchema: external_exports3.object({
|
|
32492
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional()
|
|
32493
|
+
}).superRefine((input, ctx) => {
|
|
32494
|
+
if (!input.beanId) {
|
|
32495
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["beanId"], message: BEAN_ID_HINT });
|
|
32496
|
+
}
|
|
32497
|
+
}).transform((input) => ({ ...input, beanId: input.beanId })),
|
|
32498
|
+
annotations: {
|
|
32499
|
+
readOnlyHint: false,
|
|
32500
|
+
destructiveHint: false,
|
|
32501
|
+
idempotentHint: true,
|
|
32502
|
+
openWorldHint: false
|
|
32503
|
+
}
|
|
32504
|
+
},
|
|
32505
|
+
completeTasksHandler(backend)
|
|
32506
|
+
);
|
|
31773
32507
|
server.registerTool(
|
|
31774
32508
|
"beans_query",
|
|
31775
32509
|
{
|
|
31776
32510
|
title: "Query Beans",
|
|
31777
32511
|
description: "Unified query tool for refresh, filter, search, and sort operations.",
|
|
31778
32512
|
inputSchema: external_exports3.object({
|
|
31779
|
-
operation: external_exports3.enum(["refresh", "filter", "search", "sort", "ready", "llm_context", "open_config"]).default("refresh"),
|
|
32513
|
+
operation: external_exports3.enum(["refresh", "filter", "search", "sort", "ready", "llm_context", "open_config", "graphql"]).default("refresh"),
|
|
31780
32514
|
mode: external_exports3.enum(["status-priority-type-title", "updated", "created", "id"]).optional(),
|
|
31781
32515
|
statuses: external_exports3.array(external_exports3.string().max(MAX_METADATA_LENGTH)).nullable().optional(),
|
|
31782
32516
|
types: external_exports3.array(external_exports3.string().max(MAX_METADATA_LENGTH)).nullable().optional(),
|
|
31783
32517
|
search: external_exports3.string().max(MAX_TITLE_LENGTH).optional(),
|
|
31784
32518
|
includeClosed: external_exports3.boolean().optional(),
|
|
31785
32519
|
tags: external_exports3.array(external_exports3.string().max(MAX_METADATA_LENGTH)).nullable().optional(),
|
|
32520
|
+
graphql: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
32521
|
+
variables: external_exports3.record(external_exports3.string(), external_exports3.unknown()).optional(),
|
|
31786
32522
|
writeToWorkspaceInstructions: external_exports3.boolean().optional()
|
|
32523
|
+
}).superRefine((input, ctx) => {
|
|
32524
|
+
if (input.operation === "graphql" && (!input.graphql || input.graphql.trim().length === 0)) {
|
|
32525
|
+
ctx.addIssue({
|
|
32526
|
+
code: external_exports3.ZodIssueCode.custom,
|
|
32527
|
+
path: ["graphql"],
|
|
32528
|
+
message: "graphql query string is required when operation is graphql"
|
|
32529
|
+
});
|
|
32530
|
+
}
|
|
31787
32531
|
}),
|
|
31788
32532
|
annotations: {
|
|
31789
|
-
readOnlyHint:
|
|
32533
|
+
readOnlyHint: false,
|
|
31790
32534
|
destructiveHint: false,
|
|
31791
|
-
idempotentHint:
|
|
32535
|
+
idempotentHint: false,
|
|
31792
32536
|
openWorldHint: false
|
|
31793
32537
|
}
|
|
31794
32538
|
},
|
|
@@ -31800,10 +32544,33 @@ function registerTools(server, backend) {
|
|
|
31800
32544
|
title: "Bean File Operations",
|
|
31801
32545
|
description: "Read, create, edit, or delete files under .beans (operation param).",
|
|
31802
32546
|
inputSchema: external_exports3.object({
|
|
31803
|
-
operation: external_exports3.enum(["read", "edit", "create", "delete"]),
|
|
32547
|
+
operation: external_exports3.enum(["read", "edit", "create", "delete", "update_frontmatter"]),
|
|
31804
32548
|
path: external_exports3.string().min(1).max(MAX_PATH_LENGTH),
|
|
31805
32549
|
content: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
31806
|
-
overwrite: external_exports3.boolean().optional()
|
|
32550
|
+
overwrite: external_exports3.boolean().optional(),
|
|
32551
|
+
fields: external_exports3.object({
|
|
32552
|
+
title: external_exports3.string().max(MAX_TITLE_LENGTH).optional(),
|
|
32553
|
+
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32554
|
+
type: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32555
|
+
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32556
|
+
parent_id: external_exports3.string().max(MAX_ID_LENGTH).nullable().optional(),
|
|
32557
|
+
tags: external_exports3.array(external_exports3.string().max(MAX_METADATA_LENGTH)).nullable().optional(),
|
|
32558
|
+
blocking_ids: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).nullable().optional(),
|
|
32559
|
+
blocked_by_ids: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).nullable().optional(),
|
|
32560
|
+
pr: external_exports3.string().max(MAX_TITLE_LENGTH).nullable().optional(),
|
|
32561
|
+
branch: external_exports3.string().max(MAX_TITLE_LENGTH).nullable().optional()
|
|
32562
|
+
}).optional()
|
|
32563
|
+
}).superRefine((input, ctx) => {
|
|
32564
|
+
if (input.operation === "update_frontmatter") {
|
|
32565
|
+
const fieldCount = Object.values(input.fields || {}).filter((value) => value !== void 0).length;
|
|
32566
|
+
if (fieldCount === 0) {
|
|
32567
|
+
ctx.addIssue({
|
|
32568
|
+
code: external_exports3.ZodIssueCode.custom,
|
|
32569
|
+
path: ["fields"],
|
|
32570
|
+
message: "At least one frontmatter field update is required"
|
|
32571
|
+
});
|
|
32572
|
+
}
|
|
32573
|
+
}
|
|
31807
32574
|
}),
|
|
31808
32575
|
annotations: {
|
|
31809
32576
|
readOnlyHint: false,
|
|
@@ -31843,6 +32610,18 @@ var MutableBackend = class {
|
|
|
31843
32610
|
init(prefix) {
|
|
31844
32611
|
return this.inner.init(prefix);
|
|
31845
32612
|
}
|
|
32613
|
+
archive() {
|
|
32614
|
+
if (typeof this.inner.archive === "function") {
|
|
32615
|
+
return this.inner.archive();
|
|
32616
|
+
}
|
|
32617
|
+
throw new TypeError("Archive is not supported by backend");
|
|
32618
|
+
}
|
|
32619
|
+
queryGraphql(query, variables) {
|
|
32620
|
+
if (typeof this.inner.queryGraphql === "function") {
|
|
32621
|
+
return this.inner.queryGraphql(query, variables);
|
|
32622
|
+
}
|
|
32623
|
+
throw new TypeError("GraphQL passthrough is not supported by backend");
|
|
32624
|
+
}
|
|
31846
32625
|
list(opts) {
|
|
31847
32626
|
return this.inner.list(opts);
|
|
31848
32627
|
}
|
|
@@ -31855,6 +32634,12 @@ var MutableBackend = class {
|
|
|
31855
32634
|
delete(id) {
|
|
31856
32635
|
return this.inner.delete(id);
|
|
31857
32636
|
}
|
|
32637
|
+
bulkCreate(beans, defaultParent) {
|
|
32638
|
+
return this.inner.bulkCreate(beans, defaultParent);
|
|
32639
|
+
}
|
|
32640
|
+
bulkUpdate(beans, defaultParent) {
|
|
32641
|
+
return this.inner.bulkUpdate(beans, defaultParent);
|
|
32642
|
+
}
|
|
31858
32643
|
openConfig() {
|
|
31859
32644
|
return this.inner.openConfig();
|
|
31860
32645
|
}
|
|
@@ -31876,6 +32661,9 @@ var MutableBackend = class {
|
|
|
31876
32661
|
editBeanFile(path, content) {
|
|
31877
32662
|
return this.inner.editBeanFile(path, content);
|
|
31878
32663
|
}
|
|
32664
|
+
updateBeanFrontmatter(path, updates) {
|
|
32665
|
+
return this.inner.updateBeanFrontmatter(path, updates);
|
|
32666
|
+
}
|
|
31879
32667
|
createBeanFile(path, content, opts) {
|
|
31880
32668
|
return this.inner.createBeanFile(path, content, opts);
|
|
31881
32669
|
}
|
|
@@ -31942,6 +32730,16 @@ function parseCliArgs(argv) {
|
|
|
31942
32730
|
const envPort = Number.parseInt(process.env.BEANS_VSCODE_MCP_PORT || process.env.BEANS_MCP_PORT || "", 10);
|
|
31943
32731
|
let port = Number.isInteger(envPort) && envPort > 0 ? envPort : DEFAULT_MCP_PORT;
|
|
31944
32732
|
let logDir;
|
|
32733
|
+
const parseStrictPositiveInt = (raw, flagName) => {
|
|
32734
|
+
if (!/^\d+$/.test(raw)) {
|
|
32735
|
+
throw new Error(`Invalid value for ${flagName}: ${raw}`);
|
|
32736
|
+
}
|
|
32737
|
+
const parsed = Number.parseInt(raw, 10);
|
|
32738
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
32739
|
+
throw new Error(`Invalid value for ${flagName}: ${raw}`);
|
|
32740
|
+
}
|
|
32741
|
+
return parsed;
|
|
32742
|
+
};
|
|
31945
32743
|
for (let i = 0; i < argv.length; i += 1) {
|
|
31946
32744
|
const arg = argv[i];
|
|
31947
32745
|
if ((arg === "--workspace" || arg === "--workspace-root") && argv[i + 1]) {
|
|
@@ -31955,10 +32753,7 @@ function parseCliArgs(argv) {
|
|
|
31955
32753
|
}
|
|
31956
32754
|
i += 1;
|
|
31957
32755
|
} else if (arg === "--port" && argv[i + 1]) {
|
|
31958
|
-
|
|
31959
|
-
if (Number.isInteger(parsedPort) && parsedPort > 0) {
|
|
31960
|
-
port = parsedPort;
|
|
31961
|
-
}
|
|
32756
|
+
port = parseStrictPositiveInt(argv[i + 1], "--port");
|
|
31962
32757
|
i += 1;
|
|
31963
32758
|
} else if (arg === "--log-dir" && argv[i + 1]) {
|
|
31964
32759
|
logDir = argv[i + 1];
|
|
@@ -32022,6 +32817,7 @@ init_utils();
|
|
|
32022
32817
|
DEFAULT_MCP_PORT,
|
|
32023
32818
|
MAX_ID_LENGTH,
|
|
32024
32819
|
MAX_METADATA_LENGTH,
|
|
32820
|
+
MAX_PATH_LENGTH,
|
|
32025
32821
|
MAX_TITLE_LENGTH,
|
|
32026
32822
|
createBeansMcpServer,
|
|
32027
32823
|
isPathWithinRoot,
|