@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/beans-mcp-server.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();
|
|
@@ -27126,7 +27524,7 @@ init_core2();
|
|
|
27126
27524
|
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/mini/coerce.js
|
|
27127
27525
|
init_core2();
|
|
27128
27526
|
|
|
27129
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
27527
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
|
|
27130
27528
|
function isZ4Schema(s) {
|
|
27131
27529
|
const schema = s;
|
|
27132
27530
|
return !!schema._zod;
|
|
@@ -27270,10 +27668,10 @@ function getLiteralValue(schema) {
|
|
|
27270
27668
|
return void 0;
|
|
27271
27669
|
}
|
|
27272
27670
|
|
|
27273
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
27671
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
|
|
27274
27672
|
init_types();
|
|
27275
27673
|
|
|
27276
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
27674
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
|
|
27277
27675
|
function isTerminal(status) {
|
|
27278
27676
|
return status === "completed" || status === "failed" || status === "cancelled";
|
|
27279
27677
|
}
|
|
@@ -28562,7 +28960,7 @@ var zodToJsonSchema = (schema, options) => {
|
|
|
28562
28960
|
return combined;
|
|
28563
28961
|
};
|
|
28564
28962
|
|
|
28565
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
28963
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
|
|
28566
28964
|
function mapMiniTarget(t) {
|
|
28567
28965
|
if (!t)
|
|
28568
28966
|
return "draft-7";
|
|
@@ -28604,7 +29002,7 @@ function parseWithCompat(schema, data) {
|
|
|
28604
29002
|
return result.data;
|
|
28605
29003
|
}
|
|
28606
29004
|
|
|
28607
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
29005
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
|
|
28608
29006
|
var DEFAULT_REQUEST_TIMEOUT_MSEC = 6e4;
|
|
28609
29007
|
var Protocol = class {
|
|
28610
29008
|
constructor(_options) {
|
|
@@ -28816,6 +29214,10 @@ var Protocol = class {
|
|
|
28816
29214
|
this._progressHandlers.clear();
|
|
28817
29215
|
this._taskProgressTokens.clear();
|
|
28818
29216
|
this._pendingDebouncedNotifications.clear();
|
|
29217
|
+
for (const info of this._timeoutInfo.values()) {
|
|
29218
|
+
clearTimeout(info.timeoutId);
|
|
29219
|
+
}
|
|
29220
|
+
this._timeoutInfo.clear();
|
|
28819
29221
|
for (const controller of this._requestHandlerAbortControllers.values()) {
|
|
28820
29222
|
controller.abort();
|
|
28821
29223
|
}
|
|
@@ -28946,7 +29348,9 @@ var Protocol = class {
|
|
|
28946
29348
|
await capturedTransport?.send(errorResponse);
|
|
28947
29349
|
}
|
|
28948
29350
|
}).catch((error48) => this._onerror(new Error(`Failed to send response: ${error48}`))).finally(() => {
|
|
28949
|
-
this._requestHandlerAbortControllers.
|
|
29351
|
+
if (this._requestHandlerAbortControllers.get(request.id) === abortController) {
|
|
29352
|
+
this._requestHandlerAbortControllers.delete(request.id);
|
|
29353
|
+
}
|
|
28950
29354
|
});
|
|
28951
29355
|
}
|
|
28952
29356
|
_onprogress(notification) {
|
|
@@ -29552,10 +29956,10 @@ function mergeCapabilities(base, additional) {
|
|
|
29552
29956
|
return result;
|
|
29553
29957
|
}
|
|
29554
29958
|
|
|
29555
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
29959
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
|
|
29556
29960
|
init_types();
|
|
29557
29961
|
|
|
29558
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
29962
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/validation/ajv-provider.js
|
|
29559
29963
|
var import_ajv = __toESM(require_ajv(), 1);
|
|
29560
29964
|
var import_ajv_formats = __toESM(require_dist(), 1);
|
|
29561
29965
|
function createDefaultAjvInstance() {
|
|
@@ -29623,7 +30027,7 @@ var AjvJsonSchemaValidator = class {
|
|
|
29623
30027
|
}
|
|
29624
30028
|
};
|
|
29625
30029
|
|
|
29626
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30030
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/server.js
|
|
29627
30031
|
init_types();
|
|
29628
30032
|
var ExperimentalServerTasks = class {
|
|
29629
30033
|
constructor(_server) {
|
|
@@ -29837,7 +30241,7 @@ var ExperimentalServerTasks = class {
|
|
|
29837
30241
|
}
|
|
29838
30242
|
};
|
|
29839
30243
|
|
|
29840
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30244
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js
|
|
29841
30245
|
function assertToolsCallTaskCapability(requests, method, entityName) {
|
|
29842
30246
|
if (!requests) {
|
|
29843
30247
|
throw new Error(`${entityName} does not support task creation (required for ${method})`);
|
|
@@ -29872,7 +30276,7 @@ function assertClientRequestTaskCapability(requests, method, entityName) {
|
|
|
29872
30276
|
}
|
|
29873
30277
|
}
|
|
29874
30278
|
|
|
29875
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30279
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
|
|
29876
30280
|
var Server = class extends Protocol {
|
|
29877
30281
|
/**
|
|
29878
30282
|
* Initializes this server with the given name and version information.
|
|
@@ -30252,10 +30656,10 @@ var Server = class extends Protocol {
|
|
|
30252
30656
|
}
|
|
30253
30657
|
};
|
|
30254
30658
|
|
|
30255
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30659
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
|
|
30256
30660
|
init_types();
|
|
30257
30661
|
|
|
30258
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30662
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/completable.js
|
|
30259
30663
|
var COMPLETABLE_SYMBOL = /* @__PURE__ */ Symbol.for("mcp.completable");
|
|
30260
30664
|
function isCompletable(schema) {
|
|
30261
30665
|
return !!schema && typeof schema === "object" && COMPLETABLE_SYMBOL in schema;
|
|
@@ -30269,7 +30673,7 @@ var McpZodTypeKind;
|
|
|
30269
30673
|
McpZodTypeKind2["Completable"] = "McpCompletable";
|
|
30270
30674
|
})(McpZodTypeKind || (McpZodTypeKind = {}));
|
|
30271
30675
|
|
|
30272
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30676
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/toolNameValidation.js
|
|
30273
30677
|
var TOOL_NAME_REGEX = /^[A-Za-z0-9._-]{1,128}$/;
|
|
30274
30678
|
function validateToolName(name) {
|
|
30275
30679
|
const warnings = [];
|
|
@@ -30327,7 +30731,7 @@ function validateAndWarnToolName(name) {
|
|
|
30327
30731
|
return result.isValid;
|
|
30328
30732
|
}
|
|
30329
30733
|
|
|
30330
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30734
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/mcp-server.js
|
|
30331
30735
|
var ExperimentalMcpServerTasks = class {
|
|
30332
30736
|
constructor(_mcpServer) {
|
|
30333
30737
|
this._mcpServer = _mcpServer;
|
|
@@ -30346,7 +30750,7 @@ var ExperimentalMcpServerTasks = class {
|
|
|
30346
30750
|
init_external();
|
|
30347
30751
|
init_external();
|
|
30348
30752
|
|
|
30349
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30753
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
|
|
30350
30754
|
var McpServer = class {
|
|
30351
30755
|
constructor(serverInfo, options) {
|
|
30352
30756
|
this._registeredResources = {};
|
|
@@ -30970,6 +31374,9 @@ var McpServer = class {
|
|
|
30970
31374
|
annotations = rest.shift();
|
|
30971
31375
|
}
|
|
30972
31376
|
} else if (typeof firstArg === "object" && firstArg !== null) {
|
|
31377
|
+
if (Object.values(firstArg).some((v) => typeof v === "object" && v !== null)) {
|
|
31378
|
+
throw new Error(`Tool ${name} expected a Zod schema or ToolAnnotations, but received an unrecognized object`);
|
|
31379
|
+
}
|
|
30973
31380
|
annotations = rest.shift();
|
|
30974
31381
|
}
|
|
30975
31382
|
}
|
|
@@ -31088,6 +31495,9 @@ function getZodSchemaObject(schema) {
|
|
|
31088
31495
|
if (isZodRawShapeCompat(schema)) {
|
|
31089
31496
|
return objectFromShape(schema);
|
|
31090
31497
|
}
|
|
31498
|
+
if (!isZodSchemaInstance(schema)) {
|
|
31499
|
+
throw new Error("inputSchema must be a Zod schema or raw shape, received an unrecognized object");
|
|
31500
|
+
}
|
|
31091
31501
|
return schema;
|
|
31092
31502
|
}
|
|
31093
31503
|
function promptArgumentsFromSchema(schema) {
|
|
@@ -31136,6 +31546,100 @@ var EMPTY_COMPLETION_RESULT = {
|
|
|
31136
31546
|
var import_node_child_process2 = require("child_process");
|
|
31137
31547
|
var import_node_util2 = require("util");
|
|
31138
31548
|
|
|
31549
|
+
// package.json
|
|
31550
|
+
var package_default = {
|
|
31551
|
+
name: "@selfagency/beans-mcp",
|
|
31552
|
+
version: "0.6.0",
|
|
31553
|
+
private: false,
|
|
31554
|
+
description: "MCP (Model Context Protocol) server for Beans issue tracker",
|
|
31555
|
+
keywords: [
|
|
31556
|
+
"ai",
|
|
31557
|
+
"beans",
|
|
31558
|
+
"issue-tracker",
|
|
31559
|
+
"mcp",
|
|
31560
|
+
"model-context-protocol"
|
|
31561
|
+
],
|
|
31562
|
+
homepage: "https://github.com/selfagency/beans-mcp",
|
|
31563
|
+
bugs: {
|
|
31564
|
+
url: "https://github.com/selfagency/beans-mcp/issues"
|
|
31565
|
+
},
|
|
31566
|
+
license: "MIT",
|
|
31567
|
+
author: {
|
|
31568
|
+
name: "Daniel Sieradski",
|
|
31569
|
+
email: "daniel@self.agency",
|
|
31570
|
+
url: "https://self.agency"
|
|
31571
|
+
},
|
|
31572
|
+
repository: {
|
|
31573
|
+
type: "git",
|
|
31574
|
+
url: "git+https://github.com/selfagency/beans-mcp.git"
|
|
31575
|
+
},
|
|
31576
|
+
bin: {
|
|
31577
|
+
"beans-mcp": "dist/beans-mcp-server.cjs"
|
|
31578
|
+
},
|
|
31579
|
+
files: [
|
|
31580
|
+
"dist",
|
|
31581
|
+
"skills",
|
|
31582
|
+
"README.md",
|
|
31583
|
+
"LICENSE.txt"
|
|
31584
|
+
],
|
|
31585
|
+
type: "module",
|
|
31586
|
+
main: "./dist/index.cjs",
|
|
31587
|
+
module: "./dist/index.js",
|
|
31588
|
+
types: "./dist/index.d.ts",
|
|
31589
|
+
exports: {
|
|
31590
|
+
".": {
|
|
31591
|
+
types: "./dist/index.d.ts",
|
|
31592
|
+
import: "./dist/index.js",
|
|
31593
|
+
require: "./dist/index.cjs"
|
|
31594
|
+
}
|
|
31595
|
+
},
|
|
31596
|
+
scripts: {
|
|
31597
|
+
build: "tsup",
|
|
31598
|
+
"docs:dev": "vitepress dev docs",
|
|
31599
|
+
"docs:build": "vitepress build docs",
|
|
31600
|
+
"docs:preview": "vitepress preview docs",
|
|
31601
|
+
format: "oxfmt",
|
|
31602
|
+
"lint:fix": "oxlint --fix",
|
|
31603
|
+
lint: "oxlint",
|
|
31604
|
+
postbuild: "node ./scripts/write-dist-package.js",
|
|
31605
|
+
prepare: "husky",
|
|
31606
|
+
release: "zx ./scripts/release.js",
|
|
31607
|
+
"test:coverage": "vitest run --coverage",
|
|
31608
|
+
"test:watch": "vitest",
|
|
31609
|
+
test: "vitest run",
|
|
31610
|
+
"type-check": "tsc --noEmit"
|
|
31611
|
+
},
|
|
31612
|
+
devDependencies: {
|
|
31613
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
31614
|
+
"@octokit/rest": "^22.0.1",
|
|
31615
|
+
"@types/node": "25.6.0",
|
|
31616
|
+
"@vitest/coverage-v8": "^4.1.4",
|
|
31617
|
+
"@vitest/ui": "4.1.4",
|
|
31618
|
+
husky: "^9.1.7",
|
|
31619
|
+
"lint-staged": "^16.4.0",
|
|
31620
|
+
ora: "^9.3.0",
|
|
31621
|
+
oxfmt: "^0.45.0",
|
|
31622
|
+
oxlint: "^1.60.0",
|
|
31623
|
+
"oxlint-tsgolint": "^0.21.1",
|
|
31624
|
+
tsup: "8.5.1",
|
|
31625
|
+
typescript: "6.0.3",
|
|
31626
|
+
vitepress: "^1.6.4",
|
|
31627
|
+
vitest: "4.1.4",
|
|
31628
|
+
zod: "4.3.6",
|
|
31629
|
+
zx: "^8.8.5"
|
|
31630
|
+
},
|
|
31631
|
+
"lint-staged": {
|
|
31632
|
+
"src/**/*.ts": [
|
|
31633
|
+
"pnpm run lint:fix",
|
|
31634
|
+
"pnpm run format"
|
|
31635
|
+
]
|
|
31636
|
+
},
|
|
31637
|
+
engines: {
|
|
31638
|
+
node: ">=18"
|
|
31639
|
+
},
|
|
31640
|
+
mcpName: "io.github.selfagency/beans-mcp"
|
|
31641
|
+
};
|
|
31642
|
+
|
|
31139
31643
|
// src/internal/queryHelpers.ts
|
|
31140
31644
|
function sortBeansInternal(beans, mode) {
|
|
31141
31645
|
const sorted = [...beans];
|
|
@@ -31296,94 +31800,10 @@ var MAX_PATH_LENGTH = 1024;
|
|
|
31296
31800
|
|
|
31297
31801
|
// src/server/BeansMcpServer.ts
|
|
31298
31802
|
init_utils();
|
|
31299
|
-
|
|
31300
|
-
// package.json
|
|
31301
|
-
var package_default = {
|
|
31302
|
-
name: "@selfagency/beans-mcp",
|
|
31303
|
-
version: "0.4.2",
|
|
31304
|
-
private: false,
|
|
31305
|
-
description: "MCP (Model Context Protocol) server for Beans issue tracker",
|
|
31306
|
-
author: {
|
|
31307
|
-
name: "Daniel Sieradski",
|
|
31308
|
-
email: "daniel@self.agency",
|
|
31309
|
-
url: "https://self.agency"
|
|
31310
|
-
},
|
|
31311
|
-
homepage: "https://github.com/hmans/beans",
|
|
31312
|
-
bugs: {
|
|
31313
|
-
url: "https://github.com/selfagency/beans-mcp/issues"
|
|
31314
|
-
},
|
|
31315
|
-
repository: {
|
|
31316
|
-
type: "git",
|
|
31317
|
-
url: "git+https://github.com/selfagency/beans-mcp.git"
|
|
31318
|
-
},
|
|
31319
|
-
mcpName: "io.github.selfagency/beans-mcp",
|
|
31320
|
-
keywords: [
|
|
31321
|
-
"beans",
|
|
31322
|
-
"mcp",
|
|
31323
|
-
"model-context-protocol",
|
|
31324
|
-
"issue-tracker",
|
|
31325
|
-
"ai"
|
|
31326
|
-
],
|
|
31327
|
-
license: "MIT",
|
|
31328
|
-
type: "module",
|
|
31329
|
-
exports: {
|
|
31330
|
-
".": {
|
|
31331
|
-
types: "./dist/index.d.ts",
|
|
31332
|
-
import: "./dist/index.js",
|
|
31333
|
-
require: "./dist/index.cjs"
|
|
31334
|
-
}
|
|
31335
|
-
},
|
|
31336
|
-
main: "./dist/index.cjs",
|
|
31337
|
-
module: "./dist/index.js",
|
|
31338
|
-
types: "./dist/index.d.ts",
|
|
31339
|
-
bin: {
|
|
31340
|
-
"beans-mcp": "dist/beans-mcp-server.cjs"
|
|
31341
|
-
},
|
|
31342
|
-
scripts: {
|
|
31343
|
-
build: "tsup",
|
|
31344
|
-
format: "oxfmt",
|
|
31345
|
-
"lint:fix": "oxlint --fix",
|
|
31346
|
-
lint: "oxlint",
|
|
31347
|
-
postbuild: "node ./scripts/write-dist-package.js",
|
|
31348
|
-
prepare: "husky",
|
|
31349
|
-
release: "zx ./scripts/release.js",
|
|
31350
|
-
"test:coverage": "vitest run --coverage",
|
|
31351
|
-
"test:watch": "vitest",
|
|
31352
|
-
test: "vitest run",
|
|
31353
|
-
"type-check": "tsc --noEmit"
|
|
31354
|
-
},
|
|
31355
|
-
devDependencies: {
|
|
31356
|
-
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
31357
|
-
"@octokit/rest": "^22.0.1",
|
|
31358
|
-
"@types/node": "25.5.0",
|
|
31359
|
-
"@vitest/coverage-v8": "^4.1.0",
|
|
31360
|
-
"@vitest/ui": "4.1.0",
|
|
31361
|
-
husky: "^9.1.7",
|
|
31362
|
-
"lint-staged": "^16.3.3",
|
|
31363
|
-
ora: "^9.3.0",
|
|
31364
|
-
oxfmt: "^0.40.0",
|
|
31365
|
-
oxlint: "^1.55.0",
|
|
31366
|
-
"oxlint-tsgolint": "^0.16.0",
|
|
31367
|
-
tsup: "8.5.1",
|
|
31368
|
-
typescript: "^5.9.3",
|
|
31369
|
-
vitest: "4.1.0",
|
|
31370
|
-
zod: "4.3.6",
|
|
31371
|
-
zx: "^8.8.5"
|
|
31372
|
-
},
|
|
31373
|
-
engines: {
|
|
31374
|
-
node: ">=18"
|
|
31375
|
-
},
|
|
31376
|
-
"lint-staged": {
|
|
31377
|
-
"src/**/*.ts": [
|
|
31378
|
-
"pnpm run lint:fix",
|
|
31379
|
-
"pnpm run format"
|
|
31380
|
-
]
|
|
31381
|
-
}
|
|
31382
|
-
};
|
|
31383
|
-
|
|
31384
|
-
// src/server/BeansMcpServer.ts
|
|
31385
31803
|
var execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process2.execFile);
|
|
31386
31804
|
var PACKAGE_VERSION = package_default.version ?? "0.0.0-dev";
|
|
31805
|
+
var CLOSED_STATUSES = /* @__PURE__ */ new Set(["completed", "scrapped"]);
|
|
31806
|
+
var BEAN_ID_HINT = "Missing required field `beanId`. Did you mean `beanId`?";
|
|
31387
31807
|
function getSafeCliEnv(env) {
|
|
31388
31808
|
const whitelist = ["PATH", "HOME", "USER", "LANG", "LC_ALL", "LC_CTYPE", "SHELL"];
|
|
31389
31809
|
const safeEnv = {};
|
|
@@ -31404,7 +31824,8 @@ function extractVersionFromOutput(output) {
|
|
|
31404
31824
|
if (!trimmed) {
|
|
31405
31825
|
return null;
|
|
31406
31826
|
}
|
|
31407
|
-
const
|
|
31827
|
+
const versionRegex = /(?:^|[^\d])v?(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)/;
|
|
31828
|
+
const match = versionRegex.exec(trimmed);
|
|
31408
31829
|
return match?.[1] ?? null;
|
|
31409
31830
|
}
|
|
31410
31831
|
async function detectBeansCliVersion(cliPath, workspaceRoot) {
|
|
@@ -31421,10 +31842,10 @@ ${stderr}`);
|
|
|
31421
31842
|
return null;
|
|
31422
31843
|
}
|
|
31423
31844
|
}
|
|
31424
|
-
async function getBeanById(backend, beanId) {
|
|
31845
|
+
async function getBeanById(backend, beanId, beans) {
|
|
31425
31846
|
try {
|
|
31426
|
-
const
|
|
31427
|
-
const found =
|
|
31847
|
+
const allBeans = beans ?? await backend.list();
|
|
31848
|
+
const found = allBeans.find((b) => b.id === beanId);
|
|
31428
31849
|
if (!found) {
|
|
31429
31850
|
throw new Error(`Bean not found: ${beanId}`);
|
|
31430
31851
|
}
|
|
@@ -31433,12 +31854,111 @@ async function getBeanById(backend, beanId) {
|
|
|
31433
31854
|
throw new Error(`Failed to fetch bean ${beanId}: ${error48.message}`);
|
|
31434
31855
|
}
|
|
31435
31856
|
}
|
|
31857
|
+
function collectDescendantBeans(beans, rootBeanId) {
|
|
31858
|
+
const byParent = /* @__PURE__ */ new Map();
|
|
31859
|
+
const byId = new Map(beans.map((bean) => [bean.id, bean]));
|
|
31860
|
+
for (const bean of beans) {
|
|
31861
|
+
if (!bean.parentId) {
|
|
31862
|
+
continue;
|
|
31863
|
+
}
|
|
31864
|
+
const children = byParent.get(bean.parentId) ?? [];
|
|
31865
|
+
children.push(bean.id);
|
|
31866
|
+
byParent.set(bean.parentId, children);
|
|
31867
|
+
}
|
|
31868
|
+
const queue = [...byParent.get(rootBeanId) ?? []];
|
|
31869
|
+
const visited = /* @__PURE__ */ new Set();
|
|
31870
|
+
const descendants = [];
|
|
31871
|
+
while (queue.length > 0) {
|
|
31872
|
+
const currentId = queue.shift();
|
|
31873
|
+
if (!currentId || visited.has(currentId)) {
|
|
31874
|
+
continue;
|
|
31875
|
+
}
|
|
31876
|
+
visited.add(currentId);
|
|
31877
|
+
const currentBean = byId.get(currentId);
|
|
31878
|
+
if (!currentBean) {
|
|
31879
|
+
continue;
|
|
31880
|
+
}
|
|
31881
|
+
descendants.push(currentBean);
|
|
31882
|
+
const children = byParent.get(currentId);
|
|
31883
|
+
if (children && children.length > 0) {
|
|
31884
|
+
queue.push(...children);
|
|
31885
|
+
}
|
|
31886
|
+
}
|
|
31887
|
+
return descendants;
|
|
31888
|
+
}
|
|
31889
|
+
async function cascadeStatusToDescendants(backend, rootBeanId, targetStatus, options) {
|
|
31890
|
+
const beans = options?.beans ?? await backend.list();
|
|
31891
|
+
const descendants = collectDescendantBeans(beans, rootBeanId);
|
|
31892
|
+
const updatedBeanIds = [];
|
|
31893
|
+
const skippedBeanIds = [];
|
|
31894
|
+
const errors = [];
|
|
31895
|
+
const toUpdate = [];
|
|
31896
|
+
for (const bean of descendants) {
|
|
31897
|
+
if (options?.onlyCurrentStatuses && !options.onlyCurrentStatuses.has(bean.status)) {
|
|
31898
|
+
skippedBeanIds.push(bean.id);
|
|
31899
|
+
continue;
|
|
31900
|
+
}
|
|
31901
|
+
toUpdate.push(bean);
|
|
31902
|
+
}
|
|
31903
|
+
const settled = await Promise.allSettled(
|
|
31904
|
+
toUpdate.map(async (bean) => backend.update(bean.id, { status: targetStatus }))
|
|
31905
|
+
);
|
|
31906
|
+
settled.forEach((result, index) => {
|
|
31907
|
+
const bean = toUpdate[index];
|
|
31908
|
+
if (!bean) {
|
|
31909
|
+
return;
|
|
31910
|
+
}
|
|
31911
|
+
if (result.status === "fulfilled") {
|
|
31912
|
+
updatedBeanIds.push(bean.id);
|
|
31913
|
+
return;
|
|
31914
|
+
}
|
|
31915
|
+
errors.push({
|
|
31916
|
+
beanId: bean.id,
|
|
31917
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
31918
|
+
});
|
|
31919
|
+
});
|
|
31920
|
+
return {
|
|
31921
|
+
totalDescendants: descendants.length,
|
|
31922
|
+
updatedBeanIds,
|
|
31923
|
+
skippedBeanIds,
|
|
31924
|
+
errors
|
|
31925
|
+
};
|
|
31926
|
+
}
|
|
31927
|
+
function completeMarkdownTasks(body) {
|
|
31928
|
+
const lines = body.split(/\r?\n/);
|
|
31929
|
+
let totalTaskCount = 0;
|
|
31930
|
+
let updatedTaskCount = 0;
|
|
31931
|
+
const taskLinePattern = /^\s*(?:[-*+]|\d+\.)\s+\[[ xX]\]/;
|
|
31932
|
+
const uncheckedTaskLinePattern = /^(\s*(?:[-*+]|\d+\.)\s+\[)\s(\].*)$/;
|
|
31933
|
+
const nextLines = lines.map((line) => {
|
|
31934
|
+
if (!taskLinePattern.test(line)) {
|
|
31935
|
+
return line;
|
|
31936
|
+
}
|
|
31937
|
+
totalTaskCount += 1;
|
|
31938
|
+
const uncheckedMatch = uncheckedTaskLinePattern.exec(line);
|
|
31939
|
+
if (!uncheckedMatch) {
|
|
31940
|
+
return line;
|
|
31941
|
+
}
|
|
31942
|
+
updatedTaskCount += 1;
|
|
31943
|
+
return `${uncheckedMatch[1]}x${uncheckedMatch[2]}`;
|
|
31944
|
+
});
|
|
31945
|
+
const nextBody = nextLines.join("\n");
|
|
31946
|
+
return { nextBody, totalTaskCount, updatedTaskCount };
|
|
31947
|
+
}
|
|
31436
31948
|
function initHandler(backend) {
|
|
31437
31949
|
return async ({ prefix }) => {
|
|
31438
31950
|
const result = await backend.init(prefix);
|
|
31439
31951
|
return makeTextAndStructured(result);
|
|
31440
31952
|
};
|
|
31441
31953
|
}
|
|
31954
|
+
function archiveHandler(backend) {
|
|
31955
|
+
return async () => {
|
|
31956
|
+
if (typeof backend.archive !== "function") {
|
|
31957
|
+
throw new TypeError("Archive is not supported by the current backend");
|
|
31958
|
+
}
|
|
31959
|
+
return makeTextAndStructured(await backend.archive());
|
|
31960
|
+
};
|
|
31961
|
+
}
|
|
31442
31962
|
function viewHandler(backend) {
|
|
31443
31963
|
return async ({ beanId, beanIds }) => {
|
|
31444
31964
|
const ids = Array.isArray(beanIds) && beanIds.length > 0 ? beanIds : beanId ? [beanId] : [];
|
|
@@ -31453,7 +31973,12 @@ function viewHandler(backend) {
|
|
|
31453
31973
|
const byId = new Map(beans.map((b) => [b.id, b]));
|
|
31454
31974
|
const found = ids.map((id) => byId.get(id)).filter(Boolean);
|
|
31455
31975
|
const missingBeanIds = ids.filter((id) => !byId.has(id));
|
|
31456
|
-
return makeTextAndStructured({
|
|
31976
|
+
return makeTextAndStructured({
|
|
31977
|
+
beans: found,
|
|
31978
|
+
missingBeanIds,
|
|
31979
|
+
count: found.length,
|
|
31980
|
+
requestedCount: ids.length
|
|
31981
|
+
});
|
|
31457
31982
|
};
|
|
31458
31983
|
}
|
|
31459
31984
|
async function checkVersionCompatibility(cliPath, workspaceRoot, detector) {
|
|
@@ -31471,7 +31996,14 @@ async function checkVersionCompatibility(cliPath, workspaceRoot, detector) {
|
|
|
31471
31996
|
}
|
|
31472
31997
|
}
|
|
31473
31998
|
function createHandler(backend) {
|
|
31474
|
-
return async (input) =>
|
|
31999
|
+
return async (input) => {
|
|
32000
|
+
const bean = await backend.create(input);
|
|
32001
|
+
const warnings = input.description !== void 0 ? ["`description` is deprecated; use `body` instead."] : void 0;
|
|
32002
|
+
return makeTextAndStructured({
|
|
32003
|
+
bean,
|
|
32004
|
+
...warnings ? { warnings } : {}
|
|
32005
|
+
});
|
|
32006
|
+
};
|
|
31475
32007
|
}
|
|
31476
32008
|
function editHandler(backend) {
|
|
31477
32009
|
return async ({
|
|
@@ -31485,18 +32017,30 @@ function reopenHandler(backend) {
|
|
|
31485
32017
|
requiredCurrentStatus,
|
|
31486
32018
|
targetStatus
|
|
31487
32019
|
}) => {
|
|
31488
|
-
const
|
|
31489
|
-
|
|
31490
|
-
|
|
32020
|
+
const beans = await backend.list();
|
|
32021
|
+
const bean = await getBeanById(backend, beanId, beans);
|
|
32022
|
+
if (bean.status === requiredCurrentStatus) {
|
|
32023
|
+
const updatedParentBean = await backend.update(beanId, { status: targetStatus });
|
|
32024
|
+
const cascade = await cascadeStatusToDescendants(backend, beanId, targetStatus, {
|
|
32025
|
+
onlyCurrentStatuses: CLOSED_STATUSES,
|
|
32026
|
+
beans
|
|
32027
|
+
});
|
|
32028
|
+
return makeTextAndStructured({
|
|
32029
|
+
bean: updatedParentBean,
|
|
32030
|
+
cascade: {
|
|
32031
|
+
totalDescendants: cascade.totalDescendants,
|
|
32032
|
+
updatedBeanIds: cascade.updatedBeanIds,
|
|
32033
|
+
skippedBeanIds: cascade.skippedBeanIds,
|
|
32034
|
+
errors: cascade.errors
|
|
32035
|
+
}
|
|
32036
|
+
});
|
|
31491
32037
|
}
|
|
31492
|
-
|
|
31493
|
-
bean: await backend.update(beanId, { status: targetStatus })
|
|
31494
|
-
});
|
|
32038
|
+
throw new Error(`Bean ${beanId} is not ${requiredCurrentStatus}`);
|
|
31495
32039
|
};
|
|
31496
32040
|
}
|
|
31497
32041
|
function updateHandler(backend) {
|
|
31498
|
-
return async (input) =>
|
|
31499
|
-
|
|
32042
|
+
return async (input) => {
|
|
32043
|
+
const updatedBean = await backend.update(input.beanId, {
|
|
31500
32044
|
status: input.status,
|
|
31501
32045
|
type: input.type,
|
|
31502
32046
|
priority: input.priority,
|
|
@@ -31508,8 +32052,37 @@ function updateHandler(backend) {
|
|
|
31508
32052
|
bodyAppend: input.bodyAppend,
|
|
31509
32053
|
bodyReplace: input.bodyReplace,
|
|
31510
32054
|
ifMatch: input.ifMatch
|
|
31511
|
-
})
|
|
31512
|
-
|
|
32055
|
+
});
|
|
32056
|
+
const closeStatus = input.status;
|
|
32057
|
+
const shouldCascadeClose = Boolean(closeStatus && CLOSED_STATUSES.has(closeStatus));
|
|
32058
|
+
const cascade = shouldCascadeClose ? await cascadeStatusToDescendants(backend, input.beanId, closeStatus, {
|
|
32059
|
+
beans: await backend.list()
|
|
32060
|
+
}) : null;
|
|
32061
|
+
return makeTextAndStructured({
|
|
32062
|
+
bean: updatedBean,
|
|
32063
|
+
...cascade ? {
|
|
32064
|
+
cascade: {
|
|
32065
|
+
totalDescendants: cascade.totalDescendants,
|
|
32066
|
+
updatedBeanIds: cascade.updatedBeanIds,
|
|
32067
|
+
skippedBeanIds: cascade.skippedBeanIds,
|
|
32068
|
+
errors: cascade.errors
|
|
32069
|
+
}
|
|
32070
|
+
} : {}
|
|
32071
|
+
});
|
|
32072
|
+
};
|
|
32073
|
+
}
|
|
32074
|
+
function completeTasksHandler(backend) {
|
|
32075
|
+
return async ({ beanId }) => {
|
|
32076
|
+
const bean = await getBeanById(backend, beanId);
|
|
32077
|
+
const { nextBody, totalTaskCount, updatedTaskCount } = completeMarkdownTasks(bean.body || "");
|
|
32078
|
+
const updatedBean = updatedTaskCount > 0 ? await backend.update(beanId, { body: nextBody }) : bean;
|
|
32079
|
+
return makeTextAndStructured({
|
|
32080
|
+
bean: updatedBean,
|
|
32081
|
+
totalTaskCount,
|
|
32082
|
+
updatedTaskCount,
|
|
32083
|
+
unchangedTaskCount: totalTaskCount - updatedTaskCount
|
|
32084
|
+
});
|
|
32085
|
+
};
|
|
31513
32086
|
}
|
|
31514
32087
|
function deleteHandler(backend) {
|
|
31515
32088
|
return async ({ beanId, beanIds, force }) => {
|
|
@@ -31545,7 +32118,11 @@ function deleteHandler(backend) {
|
|
|
31545
32118
|
await backend.delete(id);
|
|
31546
32119
|
results.push({ beanId: id, deleted: true });
|
|
31547
32120
|
} catch (error48) {
|
|
31548
|
-
results.push({
|
|
32121
|
+
results.push({
|
|
32122
|
+
beanId: id,
|
|
32123
|
+
deleted: false,
|
|
32124
|
+
error: error48.message
|
|
32125
|
+
});
|
|
31549
32126
|
}
|
|
31550
32127
|
}
|
|
31551
32128
|
return makeTextAndStructured({
|
|
@@ -31556,15 +32133,53 @@ function deleteHandler(backend) {
|
|
|
31556
32133
|
});
|
|
31557
32134
|
};
|
|
31558
32135
|
}
|
|
32136
|
+
function bulkCreateHandler(backend) {
|
|
32137
|
+
return async (input) => {
|
|
32138
|
+
const results = await backend.bulkCreate(input.beans, input.parent);
|
|
32139
|
+
const deprecatedDescriptionCount = input.beans.filter((bean) => bean.description !== void 0).length;
|
|
32140
|
+
return makeTextAndStructured({
|
|
32141
|
+
results,
|
|
32142
|
+
requestedCount: input.beans.length,
|
|
32143
|
+
successCount: results.filter((r) => r.bean).length,
|
|
32144
|
+
failedCount: results.filter((r) => r.error).length,
|
|
32145
|
+
...deprecatedDescriptionCount > 0 ? {
|
|
32146
|
+
warnings: [
|
|
32147
|
+
`Found ${deprecatedDescriptionCount} bean(s) using deprecated field \`description\`; use \`body\` instead.`
|
|
32148
|
+
]
|
|
32149
|
+
} : {}
|
|
32150
|
+
});
|
|
32151
|
+
};
|
|
32152
|
+
}
|
|
32153
|
+
function bulkUpdateHandler(backend) {
|
|
32154
|
+
return async (input) => {
|
|
32155
|
+
const results = await backend.bulkUpdate(input.beans, input.parent);
|
|
32156
|
+
return makeTextAndStructured({
|
|
32157
|
+
results,
|
|
32158
|
+
requestedCount: input.beans.length,
|
|
32159
|
+
successCount: results.filter((r) => r.bean).length,
|
|
32160
|
+
failedCount: results.filter((r) => r.error).length
|
|
32161
|
+
});
|
|
32162
|
+
};
|
|
32163
|
+
}
|
|
31559
32164
|
function queryHandler(backend) {
|
|
31560
|
-
return async (opts) =>
|
|
32165
|
+
return async (opts) => {
|
|
32166
|
+
if (opts.operation === "graphql") {
|
|
32167
|
+
if (typeof backend.queryGraphql !== "function") {
|
|
32168
|
+
throw new TypeError("GraphQL passthrough is not supported by the current backend");
|
|
32169
|
+
}
|
|
32170
|
+
const result = await backend.queryGraphql(opts.graphql || "", opts.variables);
|
|
32171
|
+
return makeTextAndStructured({ data: result.data, errors: result.errors ?? [] });
|
|
32172
|
+
}
|
|
32173
|
+
return handleQueryOperation(backend, opts);
|
|
32174
|
+
};
|
|
31561
32175
|
}
|
|
31562
32176
|
function beanFileHandler(backend) {
|
|
31563
32177
|
return async ({
|
|
31564
32178
|
operation,
|
|
31565
32179
|
path,
|
|
31566
32180
|
content,
|
|
31567
|
-
overwrite
|
|
32181
|
+
overwrite,
|
|
32182
|
+
fields
|
|
31568
32183
|
}) => {
|
|
31569
32184
|
if (operation === "read") {
|
|
31570
32185
|
return makeTextAndStructured(await backend.readBeanFile(path));
|
|
@@ -31575,6 +32190,9 @@ function beanFileHandler(backend) {
|
|
|
31575
32190
|
if (operation === "create") {
|
|
31576
32191
|
return makeTextAndStructured(await backend.createBeanFile(path, content || "", { overwrite }));
|
|
31577
32192
|
}
|
|
32193
|
+
if (operation === "update_frontmatter") {
|
|
32194
|
+
return makeTextAndStructured(await backend.updateBeanFrontmatter(path, fields || {}));
|
|
32195
|
+
}
|
|
31578
32196
|
if (operation === "delete") {
|
|
31579
32197
|
return makeTextAndStructured(await backend.deleteBeanFile(path));
|
|
31580
32198
|
}
|
|
@@ -31609,6 +32227,21 @@ function registerTools(server, backend) {
|
|
|
31609
32227
|
},
|
|
31610
32228
|
initHandler(backend)
|
|
31611
32229
|
);
|
|
32230
|
+
server.registerTool(
|
|
32231
|
+
"beans_archive",
|
|
32232
|
+
{
|
|
32233
|
+
title: "Archive Beans",
|
|
32234
|
+
description: "Archive completed or scrapped beans, equivalent to the beans CLI archive command.",
|
|
32235
|
+
inputSchema: external_exports3.object({}),
|
|
32236
|
+
annotations: {
|
|
32237
|
+
readOnlyHint: false,
|
|
32238
|
+
destructiveHint: false,
|
|
32239
|
+
idempotentHint: false,
|
|
32240
|
+
openWorldHint: false
|
|
32241
|
+
}
|
|
32242
|
+
},
|
|
32243
|
+
archiveHandler(backend)
|
|
32244
|
+
);
|
|
31612
32245
|
server.registerTool(
|
|
31613
32246
|
"beans_view",
|
|
31614
32247
|
{
|
|
@@ -31618,7 +32251,7 @@ function registerTools(server, backend) {
|
|
|
31618
32251
|
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
31619
32252
|
beanIds: external_exports3.array(external_exports3.string().min(1).max(MAX_ID_LENGTH)).optional()
|
|
31620
32253
|
}).refine((input) => Boolean(input.beanId) || Array.isArray(input.beanIds) && input.beanIds.length > 0, {
|
|
31621
|
-
message:
|
|
32254
|
+
message: `Either beanId or beanIds must be provided. ${BEAN_ID_HINT}`
|
|
31622
32255
|
}),
|
|
31623
32256
|
annotations: {
|
|
31624
32257
|
readOnlyHint: true,
|
|
@@ -31639,7 +32272,8 @@ function registerTools(server, backend) {
|
|
|
31639
32272
|
type: external_exports3.string().min(1).max(MAX_METADATA_LENGTH),
|
|
31640
32273
|
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31641
32274
|
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31642
|
-
|
|
32275
|
+
body: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional().describe("Body markdown content"),
|
|
32276
|
+
description: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional().describe("Deprecated alias for body"),
|
|
31643
32277
|
parent: external_exports3.string().max(MAX_ID_LENGTH).optional()
|
|
31644
32278
|
}),
|
|
31645
32279
|
annotations: {
|
|
@@ -31657,7 +32291,7 @@ function registerTools(server, backend) {
|
|
|
31657
32291
|
title: "Edit Bean Metadata",
|
|
31658
32292
|
description: "Update bean metadata fields (status/type/priority/parent/blocking).",
|
|
31659
32293
|
inputSchema: external_exports3.object({
|
|
31660
|
-
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH),
|
|
32294
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
31661
32295
|
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31662
32296
|
type: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31663
32297
|
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
@@ -31665,7 +32299,11 @@ function registerTools(server, backend) {
|
|
|
31665
32299
|
clearParent: external_exports3.boolean().optional(),
|
|
31666
32300
|
blocking: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).optional(),
|
|
31667
32301
|
blockedBy: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).optional()
|
|
31668
|
-
}),
|
|
32302
|
+
}).superRefine((input, ctx) => {
|
|
32303
|
+
if (!input.beanId) {
|
|
32304
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["beanId"], message: BEAN_ID_HINT });
|
|
32305
|
+
}
|
|
32306
|
+
}).transform((input) => ({ ...input, beanId: input.beanId })),
|
|
31669
32307
|
annotations: {
|
|
31670
32308
|
readOnlyHint: false,
|
|
31671
32309
|
destructiveHint: false,
|
|
@@ -31681,10 +32319,14 @@ function registerTools(server, backend) {
|
|
|
31681
32319
|
title: "Reopen Bean",
|
|
31682
32320
|
description: "Reopen a completed or scrapped bean into a non-closed status.",
|
|
31683
32321
|
inputSchema: external_exports3.object({
|
|
31684
|
-
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH),
|
|
32322
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
31685
32323
|
requiredCurrentStatus: external_exports3.enum(["completed", "scrapped"]),
|
|
31686
32324
|
targetStatus: external_exports3.string().max(MAX_METADATA_LENGTH).default("todo")
|
|
31687
|
-
}),
|
|
32325
|
+
}).superRefine((input, ctx) => {
|
|
32326
|
+
if (!input.beanId) {
|
|
32327
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["beanId"], message: BEAN_ID_HINT });
|
|
32328
|
+
}
|
|
32329
|
+
}).transform((input) => ({ ...input, beanId: input.beanId })),
|
|
31688
32330
|
annotations: {
|
|
31689
32331
|
readOnlyHint: false,
|
|
31690
32332
|
destructiveHint: false,
|
|
@@ -31700,7 +32342,7 @@ function registerTools(server, backend) {
|
|
|
31700
32342
|
title: "Update Bean",
|
|
31701
32343
|
description: "Update bean metadata fields (status/type/priority/parent/blocking). Consolidated replacement for per-field update tools.",
|
|
31702
32344
|
inputSchema: external_exports3.object({
|
|
31703
|
-
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH),
|
|
32345
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
31704
32346
|
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31705
32347
|
type: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31706
32348
|
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
@@ -31717,12 +32359,16 @@ function registerTools(server, backend) {
|
|
|
31717
32359
|
})
|
|
31718
32360
|
).optional(),
|
|
31719
32361
|
ifMatch: external_exports3.string().max(MAX_METADATA_LENGTH).optional()
|
|
32362
|
+
}).superRefine((input, ctx) => {
|
|
32363
|
+
if (!input.beanId) {
|
|
32364
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["beanId"], message: BEAN_ID_HINT });
|
|
32365
|
+
}
|
|
31720
32366
|
}).refine(
|
|
31721
32367
|
(input) => !(input.body !== void 0 && (input.bodyAppend !== void 0 || input.bodyReplace !== void 0)),
|
|
31722
32368
|
{
|
|
31723
32369
|
message: "body cannot be combined with bodyAppend/bodyReplace"
|
|
31724
32370
|
}
|
|
31725
|
-
),
|
|
32371
|
+
).transform((input) => ({ ...input, beanId: input.beanId })),
|
|
31726
32372
|
annotations: {
|
|
31727
32373
|
readOnlyHint: false,
|
|
31728
32374
|
destructiveHint: false,
|
|
@@ -31742,7 +32388,7 @@ function registerTools(server, backend) {
|
|
|
31742
32388
|
beanIds: external_exports3.array(external_exports3.string().min(1).max(MAX_ID_LENGTH)).optional(),
|
|
31743
32389
|
force: external_exports3.boolean().default(false)
|
|
31744
32390
|
}).refine((input) => Boolean(input.beanId) || Array.isArray(input.beanIds) && input.beanIds.length > 0, {
|
|
31745
|
-
message:
|
|
32391
|
+
message: `Either beanId or beanIds must be provided. ${BEAN_ID_HINT}`
|
|
31746
32392
|
}),
|
|
31747
32393
|
annotations: {
|
|
31748
32394
|
readOnlyHint: false,
|
|
@@ -31753,25 +32399,122 @@ function registerTools(server, backend) {
|
|
|
31753
32399
|
},
|
|
31754
32400
|
deleteHandler(backend)
|
|
31755
32401
|
);
|
|
32402
|
+
const beanCreateItemSchema = external_exports3.object({
|
|
32403
|
+
title: external_exports3.string().min(1).max(MAX_TITLE_LENGTH),
|
|
32404
|
+
type: external_exports3.string().min(1).max(MAX_METADATA_LENGTH),
|
|
32405
|
+
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32406
|
+
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32407
|
+
body: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional().describe("Body markdown content"),
|
|
32408
|
+
description: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional().describe("Deprecated alias for body"),
|
|
32409
|
+
parent: external_exports3.string().max(MAX_ID_LENGTH).optional().describe("Override the top-level parent for this item")
|
|
32410
|
+
});
|
|
32411
|
+
server.registerTool(
|
|
32412
|
+
"beans_bulk_create",
|
|
32413
|
+
{
|
|
32414
|
+
title: "Bulk Create Beans",
|
|
32415
|
+
description: "Create multiple beans in one call. Optionally assign all of them (or a subset) to a shared parent.",
|
|
32416
|
+
inputSchema: external_exports3.object({
|
|
32417
|
+
beans: external_exports3.array(beanCreateItemSchema).min(1),
|
|
32418
|
+
parent: external_exports3.string().max(MAX_ID_LENGTH).optional().describe("Default parent ID applied to any bean that does not specify its own parent")
|
|
32419
|
+
}),
|
|
32420
|
+
annotations: {
|
|
32421
|
+
readOnlyHint: false,
|
|
32422
|
+
destructiveHint: false,
|
|
32423
|
+
idempotentHint: false,
|
|
32424
|
+
openWorldHint: false
|
|
32425
|
+
}
|
|
32426
|
+
},
|
|
32427
|
+
bulkCreateHandler(backend)
|
|
32428
|
+
);
|
|
32429
|
+
const beanUpdateItemSchema = external_exports3.object({
|
|
32430
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
32431
|
+
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32432
|
+
type: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32433
|
+
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32434
|
+
parent: external_exports3.string().max(MAX_ID_LENGTH).optional().describe("Override the top-level parent for this item"),
|
|
32435
|
+
clearParent: external_exports3.boolean().optional(),
|
|
32436
|
+
blocking: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).optional(),
|
|
32437
|
+
blockedBy: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).optional(),
|
|
32438
|
+
body: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
32439
|
+
bodyAppend: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
32440
|
+
bodyReplace: external_exports3.array(external_exports3.object({ old: external_exports3.string().max(MAX_DESCRIPTION_LENGTH), new: external_exports3.string().max(MAX_DESCRIPTION_LENGTH) })).optional(),
|
|
32441
|
+
ifMatch: external_exports3.string().max(MAX_METADATA_LENGTH).optional()
|
|
32442
|
+
}).superRefine((input, ctx) => {
|
|
32443
|
+
if (!input.beanId) {
|
|
32444
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["beanId"], message: BEAN_ID_HINT });
|
|
32445
|
+
}
|
|
32446
|
+
}).refine(
|
|
32447
|
+
(input) => !(input.body !== void 0 && (input.bodyAppend !== void 0 || input.bodyReplace !== void 0)),
|
|
32448
|
+
{ message: "body cannot be combined with bodyAppend/bodyReplace" }
|
|
32449
|
+
).transform((input) => ({ ...input, beanId: input.beanId }));
|
|
32450
|
+
server.registerTool(
|
|
32451
|
+
"beans_bulk_update",
|
|
32452
|
+
{
|
|
32453
|
+
title: "Bulk Update Beans",
|
|
32454
|
+
description: "Update multiple beans in one call. Optionally assign all of them (or a subset) to a shared parent.",
|
|
32455
|
+
inputSchema: external_exports3.object({
|
|
32456
|
+
beans: external_exports3.array(beanUpdateItemSchema).min(1),
|
|
32457
|
+
parent: external_exports3.string().max(MAX_ID_LENGTH).optional().describe("Default parent ID applied to any bean that does not specify its own parent")
|
|
32458
|
+
}),
|
|
32459
|
+
annotations: {
|
|
32460
|
+
readOnlyHint: false,
|
|
32461
|
+
destructiveHint: false,
|
|
32462
|
+
idempotentHint: false,
|
|
32463
|
+
openWorldHint: false
|
|
32464
|
+
}
|
|
32465
|
+
},
|
|
32466
|
+
bulkUpdateHandler(backend)
|
|
32467
|
+
);
|
|
32468
|
+
server.registerTool(
|
|
32469
|
+
"beans_complete_tasks",
|
|
32470
|
+
{
|
|
32471
|
+
title: "Complete Markdown Tasks",
|
|
32472
|
+
description: "Mark all markdown checklist tasks within a bean as completed.",
|
|
32473
|
+
inputSchema: external_exports3.object({
|
|
32474
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional()
|
|
32475
|
+
}).superRefine((input, ctx) => {
|
|
32476
|
+
if (!input.beanId) {
|
|
32477
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["beanId"], message: BEAN_ID_HINT });
|
|
32478
|
+
}
|
|
32479
|
+
}).transform((input) => ({ ...input, beanId: input.beanId })),
|
|
32480
|
+
annotations: {
|
|
32481
|
+
readOnlyHint: false,
|
|
32482
|
+
destructiveHint: false,
|
|
32483
|
+
idempotentHint: true,
|
|
32484
|
+
openWorldHint: false
|
|
32485
|
+
}
|
|
32486
|
+
},
|
|
32487
|
+
completeTasksHandler(backend)
|
|
32488
|
+
);
|
|
31756
32489
|
server.registerTool(
|
|
31757
32490
|
"beans_query",
|
|
31758
32491
|
{
|
|
31759
32492
|
title: "Query Beans",
|
|
31760
32493
|
description: "Unified query tool for refresh, filter, search, and sort operations.",
|
|
31761
32494
|
inputSchema: external_exports3.object({
|
|
31762
|
-
operation: external_exports3.enum(["refresh", "filter", "search", "sort", "ready", "llm_context", "open_config"]).default("refresh"),
|
|
32495
|
+
operation: external_exports3.enum(["refresh", "filter", "search", "sort", "ready", "llm_context", "open_config", "graphql"]).default("refresh"),
|
|
31763
32496
|
mode: external_exports3.enum(["status-priority-type-title", "updated", "created", "id"]).optional(),
|
|
31764
32497
|
statuses: external_exports3.array(external_exports3.string().max(MAX_METADATA_LENGTH)).nullable().optional(),
|
|
31765
32498
|
types: external_exports3.array(external_exports3.string().max(MAX_METADATA_LENGTH)).nullable().optional(),
|
|
31766
32499
|
search: external_exports3.string().max(MAX_TITLE_LENGTH).optional(),
|
|
31767
32500
|
includeClosed: external_exports3.boolean().optional(),
|
|
31768
32501
|
tags: external_exports3.array(external_exports3.string().max(MAX_METADATA_LENGTH)).nullable().optional(),
|
|
32502
|
+
graphql: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
32503
|
+
variables: external_exports3.record(external_exports3.string(), external_exports3.unknown()).optional(),
|
|
31769
32504
|
writeToWorkspaceInstructions: external_exports3.boolean().optional()
|
|
32505
|
+
}).superRefine((input, ctx) => {
|
|
32506
|
+
if (input.operation === "graphql" && (!input.graphql || input.graphql.trim().length === 0)) {
|
|
32507
|
+
ctx.addIssue({
|
|
32508
|
+
code: external_exports3.ZodIssueCode.custom,
|
|
32509
|
+
path: ["graphql"],
|
|
32510
|
+
message: "graphql query string is required when operation is graphql"
|
|
32511
|
+
});
|
|
32512
|
+
}
|
|
31770
32513
|
}),
|
|
31771
32514
|
annotations: {
|
|
31772
|
-
readOnlyHint:
|
|
32515
|
+
readOnlyHint: false,
|
|
31773
32516
|
destructiveHint: false,
|
|
31774
|
-
idempotentHint:
|
|
32517
|
+
idempotentHint: false,
|
|
31775
32518
|
openWorldHint: false
|
|
31776
32519
|
}
|
|
31777
32520
|
},
|
|
@@ -31783,10 +32526,33 @@ function registerTools(server, backend) {
|
|
|
31783
32526
|
title: "Bean File Operations",
|
|
31784
32527
|
description: "Read, create, edit, or delete files under .beans (operation param).",
|
|
31785
32528
|
inputSchema: external_exports3.object({
|
|
31786
|
-
operation: external_exports3.enum(["read", "edit", "create", "delete"]),
|
|
32529
|
+
operation: external_exports3.enum(["read", "edit", "create", "delete", "update_frontmatter"]),
|
|
31787
32530
|
path: external_exports3.string().min(1).max(MAX_PATH_LENGTH),
|
|
31788
32531
|
content: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
31789
|
-
overwrite: external_exports3.boolean().optional()
|
|
32532
|
+
overwrite: external_exports3.boolean().optional(),
|
|
32533
|
+
fields: external_exports3.object({
|
|
32534
|
+
title: external_exports3.string().max(MAX_TITLE_LENGTH).optional(),
|
|
32535
|
+
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32536
|
+
type: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32537
|
+
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32538
|
+
parent_id: external_exports3.string().max(MAX_ID_LENGTH).nullable().optional(),
|
|
32539
|
+
tags: external_exports3.array(external_exports3.string().max(MAX_METADATA_LENGTH)).nullable().optional(),
|
|
32540
|
+
blocking_ids: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).nullable().optional(),
|
|
32541
|
+
blocked_by_ids: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).nullable().optional(),
|
|
32542
|
+
pr: external_exports3.string().max(MAX_TITLE_LENGTH).nullable().optional(),
|
|
32543
|
+
branch: external_exports3.string().max(MAX_TITLE_LENGTH).nullable().optional()
|
|
32544
|
+
}).optional()
|
|
32545
|
+
}).superRefine((input, ctx) => {
|
|
32546
|
+
if (input.operation === "update_frontmatter") {
|
|
32547
|
+
const fieldCount = Object.values(input.fields || {}).filter((value) => value !== void 0).length;
|
|
32548
|
+
if (fieldCount === 0) {
|
|
32549
|
+
ctx.addIssue({
|
|
32550
|
+
code: external_exports3.ZodIssueCode.custom,
|
|
32551
|
+
path: ["fields"],
|
|
32552
|
+
message: "At least one frontmatter field update is required"
|
|
32553
|
+
});
|
|
32554
|
+
}
|
|
32555
|
+
}
|
|
31790
32556
|
}),
|
|
31791
32557
|
annotations: {
|
|
31792
32558
|
readOnlyHint: false,
|
|
@@ -31826,6 +32592,18 @@ var MutableBackend = class {
|
|
|
31826
32592
|
init(prefix) {
|
|
31827
32593
|
return this.inner.init(prefix);
|
|
31828
32594
|
}
|
|
32595
|
+
archive() {
|
|
32596
|
+
if (typeof this.inner.archive === "function") {
|
|
32597
|
+
return this.inner.archive();
|
|
32598
|
+
}
|
|
32599
|
+
throw new TypeError("Archive is not supported by backend");
|
|
32600
|
+
}
|
|
32601
|
+
queryGraphql(query, variables) {
|
|
32602
|
+
if (typeof this.inner.queryGraphql === "function") {
|
|
32603
|
+
return this.inner.queryGraphql(query, variables);
|
|
32604
|
+
}
|
|
32605
|
+
throw new TypeError("GraphQL passthrough is not supported by backend");
|
|
32606
|
+
}
|
|
31829
32607
|
list(opts) {
|
|
31830
32608
|
return this.inner.list(opts);
|
|
31831
32609
|
}
|
|
@@ -31838,6 +32616,12 @@ var MutableBackend = class {
|
|
|
31838
32616
|
delete(id) {
|
|
31839
32617
|
return this.inner.delete(id);
|
|
31840
32618
|
}
|
|
32619
|
+
bulkCreate(beans, defaultParent) {
|
|
32620
|
+
return this.inner.bulkCreate(beans, defaultParent);
|
|
32621
|
+
}
|
|
32622
|
+
bulkUpdate(beans, defaultParent) {
|
|
32623
|
+
return this.inner.bulkUpdate(beans, defaultParent);
|
|
32624
|
+
}
|
|
31841
32625
|
openConfig() {
|
|
31842
32626
|
return this.inner.openConfig();
|
|
31843
32627
|
}
|
|
@@ -31859,6 +32643,9 @@ var MutableBackend = class {
|
|
|
31859
32643
|
editBeanFile(path, content) {
|
|
31860
32644
|
return this.inner.editBeanFile(path, content);
|
|
31861
32645
|
}
|
|
32646
|
+
updateBeanFrontmatter(path, updates) {
|
|
32647
|
+
return this.inner.updateBeanFrontmatter(path, updates);
|
|
32648
|
+
}
|
|
31862
32649
|
createBeanFile(path, content, opts) {
|
|
31863
32650
|
return this.inner.createBeanFile(path, content, opts);
|
|
31864
32651
|
}
|
|
@@ -31925,6 +32712,16 @@ function parseCliArgs(argv) {
|
|
|
31925
32712
|
const envPort = Number.parseInt(process.env.BEANS_VSCODE_MCP_PORT || process.env.BEANS_MCP_PORT || "", 10);
|
|
31926
32713
|
let port = Number.isInteger(envPort) && envPort > 0 ? envPort : DEFAULT_MCP_PORT;
|
|
31927
32714
|
let logDir;
|
|
32715
|
+
const parseStrictPositiveInt = (raw, flagName) => {
|
|
32716
|
+
if (!/^\d+$/.test(raw)) {
|
|
32717
|
+
throw new Error(`Invalid value for ${flagName}: ${raw}`);
|
|
32718
|
+
}
|
|
32719
|
+
const parsed = Number.parseInt(raw, 10);
|
|
32720
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
32721
|
+
throw new Error(`Invalid value for ${flagName}: ${raw}`);
|
|
32722
|
+
}
|
|
32723
|
+
return parsed;
|
|
32724
|
+
};
|
|
31928
32725
|
for (let i = 0; i < argv.length; i += 1) {
|
|
31929
32726
|
const arg = argv[i];
|
|
31930
32727
|
if ((arg === "--workspace" || arg === "--workspace-root") && argv[i + 1]) {
|
|
@@ -31938,10 +32735,7 @@ function parseCliArgs(argv) {
|
|
|
31938
32735
|
}
|
|
31939
32736
|
i += 1;
|
|
31940
32737
|
} else if (arg === "--port" && argv[i + 1]) {
|
|
31941
|
-
|
|
31942
|
-
if (Number.isInteger(parsedPort) && parsedPort > 0) {
|
|
31943
|
-
port = parsedPort;
|
|
31944
|
-
}
|
|
32738
|
+
port = parseStrictPositiveInt(argv[i + 1], "--port");
|
|
31945
32739
|
i += 1;
|
|
31946
32740
|
} else if (arg === "--log-dir" && argv[i + 1]) {
|
|
31947
32741
|
logDir = argv[i + 1];
|