@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.js
CHANGED
|
@@ -14431,7 +14431,7 @@ var init_v4 = __esm({
|
|
|
14431
14431
|
}
|
|
14432
14432
|
});
|
|
14433
14433
|
|
|
14434
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
14434
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
|
|
14435
14435
|
function assertCompleteRequestPrompt(request) {
|
|
14436
14436
|
if (request.params.ref.type !== "ref/prompt") {
|
|
14437
14437
|
throw new TypeError(`Expected CompleteRequestPrompt, but got ${request.params.ref.type}`);
|
|
@@ -14446,7 +14446,7 @@ function assertCompleteRequestResourceTemplate(request) {
|
|
|
14446
14446
|
}
|
|
14447
14447
|
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;
|
|
14448
14448
|
var init_types = __esm({
|
|
14449
|
-
"node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
14449
|
+
"node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js"() {
|
|
14450
14450
|
"use strict";
|
|
14451
14451
|
init_v4();
|
|
14452
14452
|
LATEST_PROTOCOL_VERSION = "2025-11-25";
|
|
@@ -14458,10 +14458,9 @@ var init_types = __esm({
|
|
|
14458
14458
|
CursorSchema = string2();
|
|
14459
14459
|
TaskCreationParamsSchema = looseObject({
|
|
14460
14460
|
/**
|
|
14461
|
-
*
|
|
14462
|
-
* If null, the task has unlimited lifetime until manually cleaned up.
|
|
14461
|
+
* Requested duration in milliseconds to retain task from creation.
|
|
14463
14462
|
*/
|
|
14464
|
-
ttl:
|
|
14463
|
+
ttl: number2().optional(),
|
|
14465
14464
|
/**
|
|
14466
14465
|
* Time in milliseconds to wait between task status requests.
|
|
14467
14466
|
*/
|
|
@@ -14760,7 +14759,11 @@ var init_types = __esm({
|
|
|
14760
14759
|
/**
|
|
14761
14760
|
* Present if the client supports task creation.
|
|
14762
14761
|
*/
|
|
14763
|
-
tasks: ClientTasksCapabilitySchema.optional()
|
|
14762
|
+
tasks: ClientTasksCapabilitySchema.optional(),
|
|
14763
|
+
/**
|
|
14764
|
+
* Extensions that the client supports. Keys are extension identifiers (vendor-prefix/extension-name).
|
|
14765
|
+
*/
|
|
14766
|
+
extensions: record(string2(), AssertObjectSchema).optional()
|
|
14764
14767
|
});
|
|
14765
14768
|
InitializeRequestParamsSchema = BaseRequestParamsSchema.extend({
|
|
14766
14769
|
/**
|
|
@@ -14821,7 +14824,11 @@ var init_types = __esm({
|
|
|
14821
14824
|
/**
|
|
14822
14825
|
* Present if the server supports task creation.
|
|
14823
14826
|
*/
|
|
14824
|
-
tasks: ServerTasksCapabilitySchema.optional()
|
|
14827
|
+
tasks: ServerTasksCapabilitySchema.optional(),
|
|
14828
|
+
/**
|
|
14829
|
+
* Extensions that the server supports. Keys are extension identifiers (vendor-prefix/extension-name).
|
|
14830
|
+
*/
|
|
14831
|
+
extensions: record(string2(), AssertObjectSchema).optional()
|
|
14825
14832
|
});
|
|
14826
14833
|
InitializeResultSchema = ResultSchema.extend({
|
|
14827
14834
|
/**
|
|
@@ -15013,6 +15020,12 @@ var init_types = __esm({
|
|
|
15013
15020
|
* The MIME type of this resource, if known.
|
|
15014
15021
|
*/
|
|
15015
15022
|
mimeType: optional(string2()),
|
|
15023
|
+
/**
|
|
15024
|
+
* The size of the raw resource content, in bytes (i.e., before base64 encoding or any tokenization), if known.
|
|
15025
|
+
*
|
|
15026
|
+
* This can be used by Hosts to display file sizes and estimate context window usage.
|
|
15027
|
+
*/
|
|
15028
|
+
size: optional(number2()),
|
|
15016
15029
|
/**
|
|
15017
15030
|
* Optional annotations for the client.
|
|
15018
15031
|
*/
|
|
@@ -22744,7 +22757,7 @@ var init_utils = __esm({
|
|
|
22744
22757
|
});
|
|
22745
22758
|
|
|
22746
22759
|
// src/internal/graphql.ts
|
|
22747
|
-
var LIST_BEANS_QUERY, CREATE_BEAN_MUTATION, UPDATE_BEAN_MUTATION, UPDATE_BEAN_MUTATION_WITH_IF_MATCH, DELETE_BEAN_MUTATION;
|
|
22760
|
+
var LIST_BEANS_QUERY, CREATE_BEAN_MUTATION, UPDATE_BEAN_MUTATION, UPDATE_BEAN_MUTATION_WITH_IF_MATCH, DELETE_BEAN_MUTATION, LIST_BEANS_TIMESTAMPS_QUERY;
|
|
22748
22761
|
var init_graphql = __esm({
|
|
22749
22762
|
"src/internal/graphql.ts"() {
|
|
22750
22763
|
"use strict";
|
|
@@ -22772,6 +22785,11 @@ var init_graphql = __esm({
|
|
|
22772
22785
|
mutation($id: ID!) {
|
|
22773
22786
|
deleteBean(id: $id)
|
|
22774
22787
|
}
|
|
22788
|
+
`;
|
|
22789
|
+
LIST_BEANS_TIMESTAMPS_QUERY = `
|
|
22790
|
+
query {
|
|
22791
|
+
beans { id updatedAt }
|
|
22792
|
+
}
|
|
22775
22793
|
`;
|
|
22776
22794
|
}
|
|
22777
22795
|
});
|
|
@@ -22783,7 +22801,7 @@ __export(backend_exports, {
|
|
|
22783
22801
|
});
|
|
22784
22802
|
import { execFile } from "child_process";
|
|
22785
22803
|
import { createReadStream } from "fs";
|
|
22786
|
-
import { mkdir, readFile, rm, writeFile } from "fs/promises";
|
|
22804
|
+
import { mkdir, readFile, realpath, rename, rm, writeFile } from "fs/promises";
|
|
22787
22805
|
import { dirname, join, resolve as resolve2 } from "path";
|
|
22788
22806
|
import { createInterface } from "readline";
|
|
22789
22807
|
import { promisify } from "util";
|
|
@@ -22794,12 +22812,26 @@ var init_backend = __esm({
|
|
|
22794
22812
|
init_graphql();
|
|
22795
22813
|
init_utils();
|
|
22796
22814
|
execFileAsync = promisify(execFile);
|
|
22797
|
-
BeansCliBackend = class {
|
|
22815
|
+
BeansCliBackend = class _BeansCliBackend {
|
|
22798
22816
|
constructor(workspaceRoot, cliPath, logDir) {
|
|
22799
22817
|
this.workspaceRoot = workspaceRoot;
|
|
22800
22818
|
this.cliPath = cliPath;
|
|
22801
22819
|
this.logDir = logDir;
|
|
22802
22820
|
}
|
|
22821
|
+
// ---------------------------------------------------------------------------
|
|
22822
|
+
// Cache
|
|
22823
|
+
// ---------------------------------------------------------------------------
|
|
22824
|
+
/** Full unfiltered records keyed by bean ID, stored under the fixed cache key `'all'`. */
|
|
22825
|
+
_cache = /* @__PURE__ */ new Map();
|
|
22826
|
+
/** Last time the unfiltered cache entry `'all'` was fetched (ms). */
|
|
22827
|
+
_cacheTime = /* @__PURE__ */ new Map();
|
|
22828
|
+
/** Short-circuit TTL: skip even the timestamp check within this window (ms). */
|
|
22829
|
+
static BURST_TTL_MS = 5e3;
|
|
22830
|
+
/** Invalidate the unfiltered list cache so the next call does a full fetch. */
|
|
22831
|
+
invalidateCache() {
|
|
22832
|
+
this._cache.delete("all");
|
|
22833
|
+
this._cacheTime.delete("all");
|
|
22834
|
+
}
|
|
22803
22835
|
/**
|
|
22804
22836
|
* Returns a safe environment for executing the Beans CLI,
|
|
22805
22837
|
* whitelisting only necessary variables.
|
|
@@ -22823,7 +22855,7 @@ var init_backend = __esm({
|
|
|
22823
22855
|
return resolve2(this.workspaceRoot, ".beans");
|
|
22824
22856
|
}
|
|
22825
22857
|
resolveBeanFilePath(relativePath) {
|
|
22826
|
-
const cleaned = relativePath.trim().replace(/^\/+/, "");
|
|
22858
|
+
const cleaned = relativePath.trim().replace(/^\/+/, "").replace(/^\.beans(?:[\\/]|$)/, "");
|
|
22827
22859
|
if (!cleaned) {
|
|
22828
22860
|
throw new Error("Path is required");
|
|
22829
22861
|
}
|
|
@@ -22870,6 +22902,26 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22870
22902
|
});
|
|
22871
22903
|
return { initialized: true };
|
|
22872
22904
|
}
|
|
22905
|
+
async archive() {
|
|
22906
|
+
const { stdout } = await execFileAsync(this.cliPath, ["archive", "--json"], {
|
|
22907
|
+
cwd: this.workspaceRoot,
|
|
22908
|
+
env: this.getSafeEnv(),
|
|
22909
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
22910
|
+
timeout: 3e4
|
|
22911
|
+
});
|
|
22912
|
+
this.invalidateCache();
|
|
22913
|
+
if (!stdout.trim()) {
|
|
22914
|
+
return { archived: true };
|
|
22915
|
+
}
|
|
22916
|
+
try {
|
|
22917
|
+
return JSON.parse(stdout);
|
|
22918
|
+
} catch {
|
|
22919
|
+
return { archived: true, output: stdout.trim() };
|
|
22920
|
+
}
|
|
22921
|
+
}
|
|
22922
|
+
async queryGraphql(query, variables) {
|
|
22923
|
+
return this.executeGraphQL(query, variables);
|
|
22924
|
+
}
|
|
22873
22925
|
async list(options) {
|
|
22874
22926
|
const filter = {};
|
|
22875
22927
|
if (options?.status && options.status.length > 0) {
|
|
@@ -22881,10 +22933,48 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22881
22933
|
if (options?.search) {
|
|
22882
22934
|
filter.search = options.search;
|
|
22883
22935
|
}
|
|
22936
|
+
const isCacheable = !filter.status && !filter.type && !filter.search;
|
|
22937
|
+
const cacheKey = "all";
|
|
22938
|
+
if (isCacheable) {
|
|
22939
|
+
const lastFetch = this._cacheTime.get(cacheKey) ?? 0;
|
|
22940
|
+
const cached2 = this._cache.get(cacheKey);
|
|
22941
|
+
const age = Date.now() - lastFetch;
|
|
22942
|
+
if (cached2 && age < _BeansCliBackend.BURST_TTL_MS) {
|
|
22943
|
+
return Array.from(cached2.values());
|
|
22944
|
+
}
|
|
22945
|
+
if (cached2) {
|
|
22946
|
+
try {
|
|
22947
|
+
const { data: tsData } = await this.executeGraphQL(
|
|
22948
|
+
LIST_BEANS_TIMESTAMPS_QUERY
|
|
22949
|
+
);
|
|
22950
|
+
const timestamps = tsData.beans;
|
|
22951
|
+
let dirty = timestamps.length !== cached2.size;
|
|
22952
|
+
if (!dirty) {
|
|
22953
|
+
for (const { id, updatedAt } of timestamps) {
|
|
22954
|
+
const existing = cached2.get(id);
|
|
22955
|
+
if (!existing || existing.updatedAt !== updatedAt) {
|
|
22956
|
+
dirty = true;
|
|
22957
|
+
break;
|
|
22958
|
+
}
|
|
22959
|
+
}
|
|
22960
|
+
}
|
|
22961
|
+
if (!dirty) {
|
|
22962
|
+
this._cacheTime.set(cacheKey, Date.now());
|
|
22963
|
+
return Array.from(cached2.values());
|
|
22964
|
+
}
|
|
22965
|
+
} catch {
|
|
22966
|
+
}
|
|
22967
|
+
}
|
|
22968
|
+
}
|
|
22884
22969
|
const { data, errors } = await this.executeGraphQL(LIST_BEANS_QUERY, { filter });
|
|
22885
22970
|
if (errors && errors.length > 0) {
|
|
22886
22971
|
throw new Error(`GraphQL error: ${errors.map((e) => e.message).join(", ")}`);
|
|
22887
22972
|
}
|
|
22973
|
+
if (isCacheable) {
|
|
22974
|
+
const byId = new Map(data.beans.map((b) => [b.id, b]));
|
|
22975
|
+
this._cache.set(cacheKey, byId);
|
|
22976
|
+
this._cacheTime.set(cacheKey, Date.now());
|
|
22977
|
+
}
|
|
22888
22978
|
return data.beans;
|
|
22889
22979
|
}
|
|
22890
22980
|
async create(input) {
|
|
@@ -22893,7 +22983,7 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22893
22983
|
type: input.type,
|
|
22894
22984
|
status: input.status,
|
|
22895
22985
|
priority: input.priority,
|
|
22896
|
-
body: input.description,
|
|
22986
|
+
body: input.body ?? input.description,
|
|
22897
22987
|
parent: input.parent
|
|
22898
22988
|
};
|
|
22899
22989
|
const { data, errors } = await this.executeGraphQL(CREATE_BEAN_MUTATION, {
|
|
@@ -22902,6 +22992,7 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22902
22992
|
if (errors && errors.length > 0) {
|
|
22903
22993
|
throw new Error(`GraphQL error: ${errors.map((e) => e.message).join(", ")}`);
|
|
22904
22994
|
}
|
|
22995
|
+
this.invalidateCache();
|
|
22905
22996
|
return data.createBean;
|
|
22906
22997
|
}
|
|
22907
22998
|
async update(beanId, updates) {
|
|
@@ -22971,6 +23062,7 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22971
23062
|
if (errors && errors.length > 0) {
|
|
22972
23063
|
throw new Error(`GraphQL error: ${errors.map((e) => e.message).join(", ")}`);
|
|
22973
23064
|
}
|
|
23065
|
+
this.invalidateCache();
|
|
22974
23066
|
return data.updateBean;
|
|
22975
23067
|
}
|
|
22976
23068
|
async delete(beanId) {
|
|
@@ -22980,8 +23072,44 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22980
23072
|
if (errors && errors.length > 0) {
|
|
22981
23073
|
throw new Error(`GraphQL error: ${errors.map((e) => e.message).join(", ")}`);
|
|
22982
23074
|
}
|
|
23075
|
+
this.invalidateCache();
|
|
22983
23076
|
return { deleted: true, beanId };
|
|
22984
23077
|
}
|
|
23078
|
+
async bulkCreate(beans, defaultParent) {
|
|
23079
|
+
const settled = await Promise.allSettled(
|
|
23080
|
+
beans.map(
|
|
23081
|
+
async (item) => this.create({
|
|
23082
|
+
...item,
|
|
23083
|
+
parent: item.parent ?? defaultParent
|
|
23084
|
+
})
|
|
23085
|
+
)
|
|
23086
|
+
);
|
|
23087
|
+
return settled.map(
|
|
23088
|
+
(result) => result.status === "fulfilled" ? { bean: result.value } : { error: result.reason instanceof Error ? result.reason.message : String(result.reason) }
|
|
23089
|
+
);
|
|
23090
|
+
}
|
|
23091
|
+
async bulkUpdate(beans, defaultParent) {
|
|
23092
|
+
const settled = await Promise.allSettled(
|
|
23093
|
+
beans.map(async ({ beanId, ...updates }) => {
|
|
23094
|
+
const resolvedParent = updates.parent ?? (updates.clearParent ? void 0 : defaultParent);
|
|
23095
|
+
const bean = await this.update(beanId, { ...updates, parent: resolvedParent });
|
|
23096
|
+
return { beanId, bean };
|
|
23097
|
+
})
|
|
23098
|
+
);
|
|
23099
|
+
return settled.map((result, index) => {
|
|
23100
|
+
const beanId = beans[index]?.beanId;
|
|
23101
|
+
if (!beanId) {
|
|
23102
|
+
return { beanId: "unknown", error: "Unknown bean id" };
|
|
23103
|
+
}
|
|
23104
|
+
if (result.status === "fulfilled") {
|
|
23105
|
+
return result.value;
|
|
23106
|
+
}
|
|
23107
|
+
return {
|
|
23108
|
+
beanId,
|
|
23109
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
23110
|
+
};
|
|
23111
|
+
});
|
|
23112
|
+
}
|
|
22985
23113
|
async openConfig() {
|
|
22986
23114
|
const configPath = join(this.workspaceRoot, ".beans.yml");
|
|
22987
23115
|
const content = await readFile(configPath, "utf8");
|
|
@@ -23015,9 +23143,12 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
23015
23143
|
const outputPath = resolve2(
|
|
23016
23144
|
process.env.BEANS_VSCODE_OUTPUT_LOG || join(this.workspaceRoot, ".vscode", "logs", "beans-output.log")
|
|
23017
23145
|
);
|
|
23018
|
-
const
|
|
23146
|
+
const canonicalOutputPath = await realpath(outputPath).catch(() => outputPath);
|
|
23147
|
+
const canonicalWorkspaceRoot = await realpath(this.workspaceRoot).catch(() => resolve2(this.workspaceRoot));
|
|
23148
|
+
const isWithinWorkspace = isPathWithinRoot(canonicalWorkspaceRoot, canonicalOutputPath);
|
|
23019
23149
|
const vscodeLogDir = process.env.BEANS_VSCODE_LOG_DIR || this.logDir ? resolve2(process.env.BEANS_VSCODE_LOG_DIR || this.logDir || "") : void 0;
|
|
23020
|
-
const
|
|
23150
|
+
const canonicalVscodeLogDir = vscodeLogDir ? await realpath(vscodeLogDir).catch(() => resolve2(vscodeLogDir)) : void 0;
|
|
23151
|
+
const isWithinVscodeLogDir = canonicalVscodeLogDir ? isPathWithinRoot(canonicalVscodeLogDir, canonicalOutputPath) : false;
|
|
23021
23152
|
if (!isWithinWorkspace && !isWithinVscodeLogDir) {
|
|
23022
23153
|
throw new Error("Output log path must stay within the workspace or VS Code log directory");
|
|
23023
23154
|
}
|
|
@@ -23040,6 +23171,219 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
23040
23171
|
linesReturned: ringBuffer.length
|
|
23041
23172
|
};
|
|
23042
23173
|
}
|
|
23174
|
+
/**
|
|
23175
|
+
* Split a YAML scalar value from any trailing inline comment.
|
|
23176
|
+
* Understands single-quoted and double-quoted YAML strings so it won't
|
|
23177
|
+
* mistake a `#` inside a quoted value for a comment delimiter.
|
|
23178
|
+
*/
|
|
23179
|
+
splitYamlInlineComment(value) {
|
|
23180
|
+
let inSingle = false;
|
|
23181
|
+
let inDouble = false;
|
|
23182
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
23183
|
+
const char = value[i];
|
|
23184
|
+
if (inSingle) {
|
|
23185
|
+
if (char === "'") {
|
|
23186
|
+
if (value[i + 1] === "'") {
|
|
23187
|
+
i += 1;
|
|
23188
|
+
} else {
|
|
23189
|
+
inSingle = false;
|
|
23190
|
+
}
|
|
23191
|
+
}
|
|
23192
|
+
continue;
|
|
23193
|
+
}
|
|
23194
|
+
if (inDouble) {
|
|
23195
|
+
if (char === "\\") {
|
|
23196
|
+
i += 1;
|
|
23197
|
+
continue;
|
|
23198
|
+
}
|
|
23199
|
+
if (char === '"') {
|
|
23200
|
+
inDouble = false;
|
|
23201
|
+
}
|
|
23202
|
+
continue;
|
|
23203
|
+
}
|
|
23204
|
+
if (char === "'") {
|
|
23205
|
+
inSingle = true;
|
|
23206
|
+
continue;
|
|
23207
|
+
}
|
|
23208
|
+
if (char === '"') {
|
|
23209
|
+
inDouble = true;
|
|
23210
|
+
continue;
|
|
23211
|
+
}
|
|
23212
|
+
if (char === "#" && i > 0 && /\s/.test(value[i - 1])) {
|
|
23213
|
+
const valuePart = value.slice(0, i).trimEnd();
|
|
23214
|
+
return {
|
|
23215
|
+
valuePart,
|
|
23216
|
+
commentPart: value.slice(valuePart.length)
|
|
23217
|
+
};
|
|
23218
|
+
}
|
|
23219
|
+
}
|
|
23220
|
+
return { valuePart: value, commentPart: "" };
|
|
23221
|
+
}
|
|
23222
|
+
/** Returns true when `value` looks like a YAML block scalar indicator (`>`, `|`, `>-`, `|-`, etc.) */
|
|
23223
|
+
isYamlBlockScalarIndicator(value) {
|
|
23224
|
+
return /^[>|][+-]?[0-9]*$/.test(value) || /^[>|][0-9]*[+-]?$/.test(value);
|
|
23225
|
+
}
|
|
23226
|
+
/** Escape a plain string for use inside a YAML double-quoted scalar. */
|
|
23227
|
+
escapeForYamlDoubleQuoted(value) {
|
|
23228
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
23229
|
+
}
|
|
23230
|
+
shouldQuoteFrontmatterValue(value) {
|
|
23231
|
+
return !/^[A-Za-z0-9._-]+$/.test(value);
|
|
23232
|
+
}
|
|
23233
|
+
parseFrontmatterLine(line) {
|
|
23234
|
+
const separatorIndex = line.indexOf(":");
|
|
23235
|
+
if (separatorIndex <= 0) {
|
|
23236
|
+
return null;
|
|
23237
|
+
}
|
|
23238
|
+
const key = line.slice(0, separatorIndex).trim();
|
|
23239
|
+
if (key.length === 0) {
|
|
23240
|
+
return null;
|
|
23241
|
+
}
|
|
23242
|
+
for (const character of key) {
|
|
23243
|
+
const isAlphaNumericUnderscore = character >= "a" && character <= "z" || character >= "A" && character <= "Z" || character >= "0" && character <= "9" || character === "_";
|
|
23244
|
+
if (!isAlphaNumericUnderscore) {
|
|
23245
|
+
return null;
|
|
23246
|
+
}
|
|
23247
|
+
}
|
|
23248
|
+
const rawValue = line.slice(separatorIndex + 1).trimStart();
|
|
23249
|
+
return { key, rawValue };
|
|
23250
|
+
}
|
|
23251
|
+
buildFrontmatterIndex(frontmatterLines) {
|
|
23252
|
+
const indexByKey = /* @__PURE__ */ new Map();
|
|
23253
|
+
frontmatterLines.forEach((line, index) => {
|
|
23254
|
+
const parsed = this.parseFrontmatterLine(line);
|
|
23255
|
+
if (!parsed) {
|
|
23256
|
+
return;
|
|
23257
|
+
}
|
|
23258
|
+
indexByKey.set(parsed.key, index);
|
|
23259
|
+
});
|
|
23260
|
+
return indexByKey;
|
|
23261
|
+
}
|
|
23262
|
+
serializeFrontmatterValue(key, value) {
|
|
23263
|
+
if (Array.isArray(value)) {
|
|
23264
|
+
return JSON.stringify(value);
|
|
23265
|
+
}
|
|
23266
|
+
if (key === "title") {
|
|
23267
|
+
return this.normalizeFrontmatterTitleValue(value);
|
|
23268
|
+
}
|
|
23269
|
+
if (this.shouldQuoteFrontmatterValue(value)) {
|
|
23270
|
+
return `"${this.escapeForYamlDoubleQuoted(value)}"`;
|
|
23271
|
+
}
|
|
23272
|
+
return value;
|
|
23273
|
+
}
|
|
23274
|
+
deserializeFrontmatterValue(value) {
|
|
23275
|
+
const trimmed = value.trim();
|
|
23276
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
23277
|
+
try {
|
|
23278
|
+
const parsed = JSON.parse(trimmed);
|
|
23279
|
+
if (Array.isArray(parsed) && parsed.every((item) => typeof item === "string")) {
|
|
23280
|
+
return parsed;
|
|
23281
|
+
}
|
|
23282
|
+
} catch {
|
|
23283
|
+
}
|
|
23284
|
+
}
|
|
23285
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
23286
|
+
return trimmed.slice(1, -1).replaceAll('\\"', '"').replaceAll("\\\\", "\\").replaceAll("''", "'");
|
|
23287
|
+
}
|
|
23288
|
+
return trimmed;
|
|
23289
|
+
}
|
|
23290
|
+
splitFrontmatterDocument(content) {
|
|
23291
|
+
const crlfOpen = content.startsWith("---\r\n");
|
|
23292
|
+
const lfOpen = content.startsWith("---\n");
|
|
23293
|
+
const eol = crlfOpen ? "\r\n" : "\n";
|
|
23294
|
+
if (!crlfOpen && !lfOpen) {
|
|
23295
|
+
return { eol: "\n", hasFrontmatter: false, frontmatterLines: [], body: content };
|
|
23296
|
+
}
|
|
23297
|
+
const openEnd = `---${eol}`.length;
|
|
23298
|
+
const closeMarker = `${eol}---`;
|
|
23299
|
+
const closeIdx = content.indexOf(closeMarker, openEnd);
|
|
23300
|
+
if (closeIdx === -1) {
|
|
23301
|
+
return { eol, hasFrontmatter: false, frontmatterLines: [], body: content };
|
|
23302
|
+
}
|
|
23303
|
+
const frontmatter = content.slice(openEnd, closeIdx);
|
|
23304
|
+
const body = content.slice(closeIdx + closeMarker.length);
|
|
23305
|
+
return {
|
|
23306
|
+
eol,
|
|
23307
|
+
hasFrontmatter: true,
|
|
23308
|
+
frontmatterLines: frontmatter.length > 0 ? frontmatter.split(eol) : [],
|
|
23309
|
+
body
|
|
23310
|
+
};
|
|
23311
|
+
}
|
|
23312
|
+
parseFrontmatterFields(frontmatterLines) {
|
|
23313
|
+
const fields = {};
|
|
23314
|
+
for (const line of frontmatterLines) {
|
|
23315
|
+
const parsed = this.parseFrontmatterLine(line);
|
|
23316
|
+
if (!parsed) {
|
|
23317
|
+
continue;
|
|
23318
|
+
}
|
|
23319
|
+
const { valuePart } = this.splitYamlInlineComment(parsed.rawValue);
|
|
23320
|
+
fields[parsed.key] = this.deserializeFrontmatterValue(valuePart);
|
|
23321
|
+
}
|
|
23322
|
+
return fields;
|
|
23323
|
+
}
|
|
23324
|
+
async writeFileAtomically(absolutePath, content) {
|
|
23325
|
+
const tempPath = `${absolutePath}.tmp-${process.pid}-${Date.now()}`;
|
|
23326
|
+
await writeFile(tempPath, content, "utf8");
|
|
23327
|
+
await rename(tempPath, absolutePath);
|
|
23328
|
+
}
|
|
23329
|
+
/**
|
|
23330
|
+
* Normalise a raw YAML title value to a double-quoted scalar.
|
|
23331
|
+
* Handles: empty, already double-quoted, single-quoted (unescaping `''`),
|
|
23332
|
+
* block-scalar indicators, and plain unquoted values.
|
|
23333
|
+
*/
|
|
23334
|
+
normalizeFrontmatterTitleValue(value) {
|
|
23335
|
+
const trimmed = value.trim();
|
|
23336
|
+
if (trimmed === "") {
|
|
23337
|
+
return '""';
|
|
23338
|
+
}
|
|
23339
|
+
if (this.isYamlBlockScalarIndicator(trimmed)) {
|
|
23340
|
+
return value;
|
|
23341
|
+
}
|
|
23342
|
+
if (/^"(?:[^"\\]|\\[\s\S])*"$/.test(trimmed)) {
|
|
23343
|
+
return trimmed;
|
|
23344
|
+
}
|
|
23345
|
+
if (/^'(?:[^']|'')*'$/.test(trimmed)) {
|
|
23346
|
+
const inner = trimmed.slice(1, -1).replace(/''/g, "'");
|
|
23347
|
+
return `"${this.escapeForYamlDoubleQuoted(inner)}"`;
|
|
23348
|
+
}
|
|
23349
|
+
return `"${this.escapeForYamlDoubleQuoted(trimmed)}"`;
|
|
23350
|
+
}
|
|
23351
|
+
/**
|
|
23352
|
+
* Ensure every `title:` line in YAML frontmatter is double-quoted.
|
|
23353
|
+
* Handles already-quoted (single or double), multi-word, and special-char values.
|
|
23354
|
+
* Preserves inline comments and handles both LF and CRLF line endings.
|
|
23355
|
+
*/
|
|
23356
|
+
quoteFrontmatterTitles(content) {
|
|
23357
|
+
const crlfOpen = content.startsWith("---\r\n");
|
|
23358
|
+
const lfOpen = content.startsWith("---\n");
|
|
23359
|
+
if (!crlfOpen && !lfOpen) {
|
|
23360
|
+
return content;
|
|
23361
|
+
}
|
|
23362
|
+
const eol = crlfOpen ? "\r\n" : "\n";
|
|
23363
|
+
const openEnd = `---${eol}`.length;
|
|
23364
|
+
const closeMarker = `${eol}---`;
|
|
23365
|
+
const closeIdx = content.indexOf(closeMarker, openEnd);
|
|
23366
|
+
if (closeIdx === -1) {
|
|
23367
|
+
return content;
|
|
23368
|
+
}
|
|
23369
|
+
const frontmatter = content.slice(openEnd, closeIdx);
|
|
23370
|
+
const rest = content.slice(closeIdx);
|
|
23371
|
+
const lines = frontmatter.split(eol);
|
|
23372
|
+
const fixedLines = lines.map((line) => {
|
|
23373
|
+
if (!line.startsWith("title:")) {
|
|
23374
|
+
return line;
|
|
23375
|
+
}
|
|
23376
|
+
const colonIdx = line.indexOf(":");
|
|
23377
|
+
const afterColon = line.slice(colonIdx + 1);
|
|
23378
|
+
const leadingSpace = afterColon.length - afterColon.trimStart().length;
|
|
23379
|
+
const raw = afterColon.trimStart();
|
|
23380
|
+
const { valuePart, commentPart } = this.splitYamlInlineComment(raw);
|
|
23381
|
+
const normalized = this.normalizeFrontmatterTitleValue(valuePart);
|
|
23382
|
+
const prefix = `title:${" ".repeat(Math.max(1, leadingSpace))}`;
|
|
23383
|
+
return `${prefix}${normalized}${commentPart}`;
|
|
23384
|
+
});
|
|
23385
|
+
return `---${eol}${fixedLines.join(eol)}${rest}`;
|
|
23386
|
+
}
|
|
23043
23387
|
async readBeanFile(relativePath) {
|
|
23044
23388
|
const absolutePath = this.resolveBeanFilePath(relativePath);
|
|
23045
23389
|
const content = await readFile(absolutePath, "utf8");
|
|
@@ -23047,20 +23391,74 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
23047
23391
|
}
|
|
23048
23392
|
async editBeanFile(relativePath, content) {
|
|
23049
23393
|
const absolutePath = this.resolveBeanFilePath(relativePath);
|
|
23394
|
+
const fixed = this.quoteFrontmatterTitles(content);
|
|
23050
23395
|
await mkdir(dirname(absolutePath), { recursive: true });
|
|
23051
|
-
await writeFile(absolutePath,
|
|
23052
|
-
return { path: absolutePath, bytes: Buffer.byteLength(
|
|
23396
|
+
await writeFile(absolutePath, fixed, "utf8");
|
|
23397
|
+
return { path: absolutePath, bytes: Buffer.byteLength(fixed, "utf8") };
|
|
23398
|
+
}
|
|
23399
|
+
async updateBeanFrontmatter(relativePath, updates) {
|
|
23400
|
+
const absolutePath = this.resolveBeanFilePath(relativePath);
|
|
23401
|
+
const content = await readFile(absolutePath, "utf8");
|
|
23402
|
+
const { eol, hasFrontmatter, frontmatterLines, body } = this.splitFrontmatterDocument(content);
|
|
23403
|
+
const updatedFields = Object.entries(updates).filter(([, value]) => value !== void 0).map(([key]) => key);
|
|
23404
|
+
if (updatedFields.length === 0) {
|
|
23405
|
+
throw new Error("At least one frontmatter field update is required");
|
|
23406
|
+
}
|
|
23407
|
+
const nextLines = [...frontmatterLines];
|
|
23408
|
+
let indexByKey = this.buildFrontmatterIndex(nextLines);
|
|
23409
|
+
for (const [key, value] of Object.entries(updates)) {
|
|
23410
|
+
if (value === void 0) {
|
|
23411
|
+
continue;
|
|
23412
|
+
}
|
|
23413
|
+
const existingIndex = indexByKey.get(key);
|
|
23414
|
+
if (value === null) {
|
|
23415
|
+
if (existingIndex !== void 0) {
|
|
23416
|
+
nextLines.splice(existingIndex, 1);
|
|
23417
|
+
indexByKey = this.buildFrontmatterIndex(nextLines);
|
|
23418
|
+
}
|
|
23419
|
+
continue;
|
|
23420
|
+
}
|
|
23421
|
+
const serialized = `${key}: ${this.serializeFrontmatterValue(key, value)}`;
|
|
23422
|
+
if (existingIndex !== void 0) {
|
|
23423
|
+
const existingLine = nextLines[existingIndex] ?? "";
|
|
23424
|
+
const existingParsed = this.parseFrontmatterLine(existingLine);
|
|
23425
|
+
const commentPart = existingParsed ? this.splitYamlInlineComment(existingParsed.rawValue).commentPart : "";
|
|
23426
|
+
nextLines[existingIndex] = `${serialized}${commentPart}`;
|
|
23427
|
+
} else {
|
|
23428
|
+
nextLines.push(serialized);
|
|
23429
|
+
indexByKey.set(key, nextLines.length - 1);
|
|
23430
|
+
}
|
|
23431
|
+
}
|
|
23432
|
+
const frontmatterBlock = nextLines.length > 0 ? nextLines.join(eol) : "";
|
|
23433
|
+
const nextContent = hasFrontmatter ? `---${eol}${frontmatterBlock}${eol}---${body}` : `---${eol}${frontmatterBlock}${eol}---${eol}${body}`;
|
|
23434
|
+
const fixed = this.quoteFrontmatterTitles(nextContent);
|
|
23435
|
+
await this.writeFileAtomically(absolutePath, fixed);
|
|
23436
|
+
return {
|
|
23437
|
+
path: absolutePath,
|
|
23438
|
+
bytes: Buffer.byteLength(fixed, "utf8"),
|
|
23439
|
+
updatedFields,
|
|
23440
|
+
frontmatter: this.parseFrontmatterFields(this.splitFrontmatterDocument(fixed).frontmatterLines)
|
|
23441
|
+
};
|
|
23053
23442
|
}
|
|
23054
23443
|
async createBeanFile(relativePath, content, options) {
|
|
23055
23444
|
const absolutePath = this.resolveBeanFilePath(relativePath);
|
|
23445
|
+
const fixed = this.quoteFrontmatterTitles(content);
|
|
23056
23446
|
await mkdir(dirname(absolutePath), { recursive: true });
|
|
23057
|
-
|
|
23058
|
-
|
|
23059
|
-
|
|
23060
|
-
|
|
23447
|
+
try {
|
|
23448
|
+
await writeFile(absolutePath, fixed, {
|
|
23449
|
+
encoding: "utf8",
|
|
23450
|
+
flag: options?.overwrite ? "w" : "wx"
|
|
23451
|
+
});
|
|
23452
|
+
} catch (error48) {
|
|
23453
|
+
const maybeNodeError = error48;
|
|
23454
|
+
if (maybeNodeError.code === "EEXIST" && !options?.overwrite) {
|
|
23455
|
+
throw new Error("Bean file already exists. Pass overwrite=true to replace it.");
|
|
23456
|
+
}
|
|
23457
|
+
throw error48;
|
|
23458
|
+
}
|
|
23061
23459
|
return {
|
|
23062
23460
|
path: absolutePath,
|
|
23063
|
-
bytes: Buffer.byteLength(
|
|
23461
|
+
bytes: Buffer.byteLength(fixed, "utf8"),
|
|
23064
23462
|
created: true
|
|
23065
23463
|
};
|
|
23066
23464
|
}
|
|
@@ -23073,7 +23471,7 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
23073
23471
|
}
|
|
23074
23472
|
});
|
|
23075
23473
|
|
|
23076
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
23474
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
|
|
23077
23475
|
function deserializeMessage(line) {
|
|
23078
23476
|
return JSONRPCMessageSchema.parse(JSON.parse(line));
|
|
23079
23477
|
}
|
|
@@ -23082,7 +23480,7 @@ function serializeMessage(message) {
|
|
|
23082
23480
|
}
|
|
23083
23481
|
var ReadBuffer;
|
|
23084
23482
|
var init_stdio = __esm({
|
|
23085
|
-
"node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
23483
|
+
"node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js"() {
|
|
23086
23484
|
"use strict";
|
|
23087
23485
|
init_types();
|
|
23088
23486
|
ReadBuffer = class {
|
|
@@ -23108,7 +23506,7 @@ var init_stdio = __esm({
|
|
|
23108
23506
|
}
|
|
23109
23507
|
});
|
|
23110
23508
|
|
|
23111
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
23509
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
23112
23510
|
var stdio_exports = {};
|
|
23113
23511
|
__export(stdio_exports, {
|
|
23114
23512
|
StdioServerTransport: () => StdioServerTransport
|
|
@@ -23116,7 +23514,7 @@ __export(stdio_exports, {
|
|
|
23116
23514
|
import process3 from "process";
|
|
23117
23515
|
var StdioServerTransport;
|
|
23118
23516
|
var init_stdio2 = __esm({
|
|
23119
|
-
"node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
23517
|
+
"node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js"() {
|
|
23120
23518
|
"use strict";
|
|
23121
23519
|
init_stdio();
|
|
23122
23520
|
StdioServerTransport = class {
|
|
@@ -27123,7 +27521,7 @@ init_core2();
|
|
|
27123
27521
|
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/mini/coerce.js
|
|
27124
27522
|
init_core2();
|
|
27125
27523
|
|
|
27126
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
27524
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
|
|
27127
27525
|
function isZ4Schema(s) {
|
|
27128
27526
|
const schema = s;
|
|
27129
27527
|
return !!schema._zod;
|
|
@@ -27267,10 +27665,10 @@ function getLiteralValue(schema) {
|
|
|
27267
27665
|
return void 0;
|
|
27268
27666
|
}
|
|
27269
27667
|
|
|
27270
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
27668
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
|
|
27271
27669
|
init_types();
|
|
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/experimental/tasks/interfaces.js
|
|
27274
27672
|
function isTerminal(status) {
|
|
27275
27673
|
return status === "completed" || status === "failed" || status === "cancelled";
|
|
27276
27674
|
}
|
|
@@ -28559,7 +28957,7 @@ var zodToJsonSchema = (schema, options) => {
|
|
|
28559
28957
|
return combined;
|
|
28560
28958
|
};
|
|
28561
28959
|
|
|
28562
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
28960
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
|
|
28563
28961
|
function mapMiniTarget(t) {
|
|
28564
28962
|
if (!t)
|
|
28565
28963
|
return "draft-7";
|
|
@@ -28601,7 +28999,7 @@ function parseWithCompat(schema, data) {
|
|
|
28601
28999
|
return result.data;
|
|
28602
29000
|
}
|
|
28603
29001
|
|
|
28604
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
29002
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
|
|
28605
29003
|
var DEFAULT_REQUEST_TIMEOUT_MSEC = 6e4;
|
|
28606
29004
|
var Protocol = class {
|
|
28607
29005
|
constructor(_options) {
|
|
@@ -28813,6 +29211,10 @@ var Protocol = class {
|
|
|
28813
29211
|
this._progressHandlers.clear();
|
|
28814
29212
|
this._taskProgressTokens.clear();
|
|
28815
29213
|
this._pendingDebouncedNotifications.clear();
|
|
29214
|
+
for (const info of this._timeoutInfo.values()) {
|
|
29215
|
+
clearTimeout(info.timeoutId);
|
|
29216
|
+
}
|
|
29217
|
+
this._timeoutInfo.clear();
|
|
28816
29218
|
for (const controller of this._requestHandlerAbortControllers.values()) {
|
|
28817
29219
|
controller.abort();
|
|
28818
29220
|
}
|
|
@@ -28943,7 +29345,9 @@ var Protocol = class {
|
|
|
28943
29345
|
await capturedTransport?.send(errorResponse);
|
|
28944
29346
|
}
|
|
28945
29347
|
}).catch((error48) => this._onerror(new Error(`Failed to send response: ${error48}`))).finally(() => {
|
|
28946
|
-
this._requestHandlerAbortControllers.
|
|
29348
|
+
if (this._requestHandlerAbortControllers.get(request.id) === abortController) {
|
|
29349
|
+
this._requestHandlerAbortControllers.delete(request.id);
|
|
29350
|
+
}
|
|
28947
29351
|
});
|
|
28948
29352
|
}
|
|
28949
29353
|
_onprogress(notification) {
|
|
@@ -29549,10 +29953,10 @@ function mergeCapabilities(base, additional) {
|
|
|
29549
29953
|
return result;
|
|
29550
29954
|
}
|
|
29551
29955
|
|
|
29552
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
29956
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
|
|
29553
29957
|
init_types();
|
|
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/validation/ajv-provider.js
|
|
29556
29960
|
var import_ajv = __toESM(require_ajv(), 1);
|
|
29557
29961
|
var import_ajv_formats = __toESM(require_dist(), 1);
|
|
29558
29962
|
function createDefaultAjvInstance() {
|
|
@@ -29620,7 +30024,7 @@ var AjvJsonSchemaValidator = class {
|
|
|
29620
30024
|
}
|
|
29621
30025
|
};
|
|
29622
30026
|
|
|
29623
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30027
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/server.js
|
|
29624
30028
|
init_types();
|
|
29625
30029
|
var ExperimentalServerTasks = class {
|
|
29626
30030
|
constructor(_server) {
|
|
@@ -29834,7 +30238,7 @@ var ExperimentalServerTasks = class {
|
|
|
29834
30238
|
}
|
|
29835
30239
|
};
|
|
29836
30240
|
|
|
29837
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30241
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js
|
|
29838
30242
|
function assertToolsCallTaskCapability(requests, method, entityName) {
|
|
29839
30243
|
if (!requests) {
|
|
29840
30244
|
throw new Error(`${entityName} does not support task creation (required for ${method})`);
|
|
@@ -29869,7 +30273,7 @@ function assertClientRequestTaskCapability(requests, method, entityName) {
|
|
|
29869
30273
|
}
|
|
29870
30274
|
}
|
|
29871
30275
|
|
|
29872
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30276
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
|
|
29873
30277
|
var Server = class extends Protocol {
|
|
29874
30278
|
/**
|
|
29875
30279
|
* Initializes this server with the given name and version information.
|
|
@@ -30249,10 +30653,10 @@ var Server = class extends Protocol {
|
|
|
30249
30653
|
}
|
|
30250
30654
|
};
|
|
30251
30655
|
|
|
30252
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30656
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
|
|
30253
30657
|
init_types();
|
|
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/completable.js
|
|
30256
30660
|
var COMPLETABLE_SYMBOL = /* @__PURE__ */ Symbol.for("mcp.completable");
|
|
30257
30661
|
function isCompletable(schema) {
|
|
30258
30662
|
return !!schema && typeof schema === "object" && COMPLETABLE_SYMBOL in schema;
|
|
@@ -30266,7 +30670,7 @@ var McpZodTypeKind;
|
|
|
30266
30670
|
McpZodTypeKind2["Completable"] = "McpCompletable";
|
|
30267
30671
|
})(McpZodTypeKind || (McpZodTypeKind = {}));
|
|
30268
30672
|
|
|
30269
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30673
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/toolNameValidation.js
|
|
30270
30674
|
var TOOL_NAME_REGEX = /^[A-Za-z0-9._-]{1,128}$/;
|
|
30271
30675
|
function validateToolName(name) {
|
|
30272
30676
|
const warnings = [];
|
|
@@ -30324,7 +30728,7 @@ function validateAndWarnToolName(name) {
|
|
|
30324
30728
|
return result.isValid;
|
|
30325
30729
|
}
|
|
30326
30730
|
|
|
30327
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30731
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/mcp-server.js
|
|
30328
30732
|
var ExperimentalMcpServerTasks = class {
|
|
30329
30733
|
constructor(_mcpServer) {
|
|
30330
30734
|
this._mcpServer = _mcpServer;
|
|
@@ -30343,7 +30747,7 @@ var ExperimentalMcpServerTasks = class {
|
|
|
30343
30747
|
init_external();
|
|
30344
30748
|
init_external();
|
|
30345
30749
|
|
|
30346
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30750
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
|
|
30347
30751
|
var McpServer = class {
|
|
30348
30752
|
constructor(serverInfo, options) {
|
|
30349
30753
|
this._registeredResources = {};
|
|
@@ -30967,6 +31371,9 @@ var McpServer = class {
|
|
|
30967
31371
|
annotations = rest.shift();
|
|
30968
31372
|
}
|
|
30969
31373
|
} else if (typeof firstArg === "object" && firstArg !== null) {
|
|
31374
|
+
if (Object.values(firstArg).some((v) => typeof v === "object" && v !== null)) {
|
|
31375
|
+
throw new Error(`Tool ${name} expected a Zod schema or ToolAnnotations, but received an unrecognized object`);
|
|
31376
|
+
}
|
|
30970
31377
|
annotations = rest.shift();
|
|
30971
31378
|
}
|
|
30972
31379
|
}
|
|
@@ -31085,6 +31492,9 @@ function getZodSchemaObject(schema) {
|
|
|
31085
31492
|
if (isZodRawShapeCompat(schema)) {
|
|
31086
31493
|
return objectFromShape(schema);
|
|
31087
31494
|
}
|
|
31495
|
+
if (!isZodSchemaInstance(schema)) {
|
|
31496
|
+
throw new Error("inputSchema must be a Zod schema or raw shape, received an unrecognized object");
|
|
31497
|
+
}
|
|
31088
31498
|
return schema;
|
|
31089
31499
|
}
|
|
31090
31500
|
function promptArgumentsFromSchema(schema) {
|
|
@@ -31133,6 +31543,100 @@ var EMPTY_COMPLETION_RESULT = {
|
|
|
31133
31543
|
import { execFile as execFile2 } from "child_process";
|
|
31134
31544
|
import { promisify as promisify2 } from "util";
|
|
31135
31545
|
|
|
31546
|
+
// package.json
|
|
31547
|
+
var package_default = {
|
|
31548
|
+
name: "@selfagency/beans-mcp",
|
|
31549
|
+
version: "0.6.0",
|
|
31550
|
+
private: false,
|
|
31551
|
+
description: "MCP (Model Context Protocol) server for Beans issue tracker",
|
|
31552
|
+
keywords: [
|
|
31553
|
+
"ai",
|
|
31554
|
+
"beans",
|
|
31555
|
+
"issue-tracker",
|
|
31556
|
+
"mcp",
|
|
31557
|
+
"model-context-protocol"
|
|
31558
|
+
],
|
|
31559
|
+
homepage: "https://github.com/selfagency/beans-mcp",
|
|
31560
|
+
bugs: {
|
|
31561
|
+
url: "https://github.com/selfagency/beans-mcp/issues"
|
|
31562
|
+
},
|
|
31563
|
+
license: "MIT",
|
|
31564
|
+
author: {
|
|
31565
|
+
name: "Daniel Sieradski",
|
|
31566
|
+
email: "daniel@self.agency",
|
|
31567
|
+
url: "https://self.agency"
|
|
31568
|
+
},
|
|
31569
|
+
repository: {
|
|
31570
|
+
type: "git",
|
|
31571
|
+
url: "git+https://github.com/selfagency/beans-mcp.git"
|
|
31572
|
+
},
|
|
31573
|
+
bin: {
|
|
31574
|
+
"beans-mcp": "dist/beans-mcp-server.cjs"
|
|
31575
|
+
},
|
|
31576
|
+
files: [
|
|
31577
|
+
"dist",
|
|
31578
|
+
"skills",
|
|
31579
|
+
"README.md",
|
|
31580
|
+
"LICENSE.txt"
|
|
31581
|
+
],
|
|
31582
|
+
type: "module",
|
|
31583
|
+
main: "./dist/index.cjs",
|
|
31584
|
+
module: "./dist/index.js",
|
|
31585
|
+
types: "./dist/index.d.ts",
|
|
31586
|
+
exports: {
|
|
31587
|
+
".": {
|
|
31588
|
+
types: "./dist/index.d.ts",
|
|
31589
|
+
import: "./dist/index.js",
|
|
31590
|
+
require: "./dist/index.cjs"
|
|
31591
|
+
}
|
|
31592
|
+
},
|
|
31593
|
+
scripts: {
|
|
31594
|
+
build: "tsup",
|
|
31595
|
+
"docs:dev": "vitepress dev docs",
|
|
31596
|
+
"docs:build": "vitepress build docs",
|
|
31597
|
+
"docs:preview": "vitepress preview docs",
|
|
31598
|
+
format: "oxfmt",
|
|
31599
|
+
"lint:fix": "oxlint --fix",
|
|
31600
|
+
lint: "oxlint",
|
|
31601
|
+
postbuild: "node ./scripts/write-dist-package.js",
|
|
31602
|
+
prepare: "husky",
|
|
31603
|
+
release: "zx ./scripts/release.js",
|
|
31604
|
+
"test:coverage": "vitest run --coverage",
|
|
31605
|
+
"test:watch": "vitest",
|
|
31606
|
+
test: "vitest run",
|
|
31607
|
+
"type-check": "tsc --noEmit"
|
|
31608
|
+
},
|
|
31609
|
+
devDependencies: {
|
|
31610
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
31611
|
+
"@octokit/rest": "^22.0.1",
|
|
31612
|
+
"@types/node": "25.6.0",
|
|
31613
|
+
"@vitest/coverage-v8": "^4.1.4",
|
|
31614
|
+
"@vitest/ui": "4.1.4",
|
|
31615
|
+
husky: "^9.1.7",
|
|
31616
|
+
"lint-staged": "^16.4.0",
|
|
31617
|
+
ora: "^9.3.0",
|
|
31618
|
+
oxfmt: "^0.45.0",
|
|
31619
|
+
oxlint: "^1.60.0",
|
|
31620
|
+
"oxlint-tsgolint": "^0.21.1",
|
|
31621
|
+
tsup: "8.5.1",
|
|
31622
|
+
typescript: "6.0.3",
|
|
31623
|
+
vitepress: "^1.6.4",
|
|
31624
|
+
vitest: "4.1.4",
|
|
31625
|
+
zod: "4.3.6",
|
|
31626
|
+
zx: "^8.8.5"
|
|
31627
|
+
},
|
|
31628
|
+
"lint-staged": {
|
|
31629
|
+
"src/**/*.ts": [
|
|
31630
|
+
"pnpm run lint:fix",
|
|
31631
|
+
"pnpm run format"
|
|
31632
|
+
]
|
|
31633
|
+
},
|
|
31634
|
+
engines: {
|
|
31635
|
+
node: ">=18"
|
|
31636
|
+
},
|
|
31637
|
+
mcpName: "io.github.selfagency/beans-mcp"
|
|
31638
|
+
};
|
|
31639
|
+
|
|
31136
31640
|
// src/internal/queryHelpers.ts
|
|
31137
31641
|
function sortBeansInternal(beans, mode) {
|
|
31138
31642
|
const sorted = [...beans];
|
|
@@ -31293,94 +31797,10 @@ var MAX_PATH_LENGTH = 1024;
|
|
|
31293
31797
|
|
|
31294
31798
|
// src/server/BeansMcpServer.ts
|
|
31295
31799
|
init_utils();
|
|
31296
|
-
|
|
31297
|
-
// package.json
|
|
31298
|
-
var package_default = {
|
|
31299
|
-
name: "@selfagency/beans-mcp",
|
|
31300
|
-
version: "0.4.2",
|
|
31301
|
-
private: false,
|
|
31302
|
-
description: "MCP (Model Context Protocol) server for Beans issue tracker",
|
|
31303
|
-
author: {
|
|
31304
|
-
name: "Daniel Sieradski",
|
|
31305
|
-
email: "daniel@self.agency",
|
|
31306
|
-
url: "https://self.agency"
|
|
31307
|
-
},
|
|
31308
|
-
homepage: "https://github.com/hmans/beans",
|
|
31309
|
-
bugs: {
|
|
31310
|
-
url: "https://github.com/selfagency/beans-mcp/issues"
|
|
31311
|
-
},
|
|
31312
|
-
repository: {
|
|
31313
|
-
type: "git",
|
|
31314
|
-
url: "git+https://github.com/selfagency/beans-mcp.git"
|
|
31315
|
-
},
|
|
31316
|
-
mcpName: "io.github.selfagency/beans-mcp",
|
|
31317
|
-
keywords: [
|
|
31318
|
-
"beans",
|
|
31319
|
-
"mcp",
|
|
31320
|
-
"model-context-protocol",
|
|
31321
|
-
"issue-tracker",
|
|
31322
|
-
"ai"
|
|
31323
|
-
],
|
|
31324
|
-
license: "MIT",
|
|
31325
|
-
type: "module",
|
|
31326
|
-
exports: {
|
|
31327
|
-
".": {
|
|
31328
|
-
types: "./dist/index.d.ts",
|
|
31329
|
-
import: "./dist/index.js",
|
|
31330
|
-
require: "./dist/index.cjs"
|
|
31331
|
-
}
|
|
31332
|
-
},
|
|
31333
|
-
main: "./dist/index.cjs",
|
|
31334
|
-
module: "./dist/index.js",
|
|
31335
|
-
types: "./dist/index.d.ts",
|
|
31336
|
-
bin: {
|
|
31337
|
-
"beans-mcp": "dist/beans-mcp-server.cjs"
|
|
31338
|
-
},
|
|
31339
|
-
scripts: {
|
|
31340
|
-
build: "tsup",
|
|
31341
|
-
format: "oxfmt",
|
|
31342
|
-
"lint:fix": "oxlint --fix",
|
|
31343
|
-
lint: "oxlint",
|
|
31344
|
-
postbuild: "node ./scripts/write-dist-package.js",
|
|
31345
|
-
prepare: "husky",
|
|
31346
|
-
release: "zx ./scripts/release.js",
|
|
31347
|
-
"test:coverage": "vitest run --coverage",
|
|
31348
|
-
"test:watch": "vitest",
|
|
31349
|
-
test: "vitest run",
|
|
31350
|
-
"type-check": "tsc --noEmit"
|
|
31351
|
-
},
|
|
31352
|
-
devDependencies: {
|
|
31353
|
-
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
31354
|
-
"@octokit/rest": "^22.0.1",
|
|
31355
|
-
"@types/node": "25.5.0",
|
|
31356
|
-
"@vitest/coverage-v8": "^4.1.0",
|
|
31357
|
-
"@vitest/ui": "4.1.0",
|
|
31358
|
-
husky: "^9.1.7",
|
|
31359
|
-
"lint-staged": "^16.3.3",
|
|
31360
|
-
ora: "^9.3.0",
|
|
31361
|
-
oxfmt: "^0.40.0",
|
|
31362
|
-
oxlint: "^1.55.0",
|
|
31363
|
-
"oxlint-tsgolint": "^0.16.0",
|
|
31364
|
-
tsup: "8.5.1",
|
|
31365
|
-
typescript: "^5.9.3",
|
|
31366
|
-
vitest: "4.1.0",
|
|
31367
|
-
zod: "4.3.6",
|
|
31368
|
-
zx: "^8.8.5"
|
|
31369
|
-
},
|
|
31370
|
-
engines: {
|
|
31371
|
-
node: ">=18"
|
|
31372
|
-
},
|
|
31373
|
-
"lint-staged": {
|
|
31374
|
-
"src/**/*.ts": [
|
|
31375
|
-
"pnpm run lint:fix",
|
|
31376
|
-
"pnpm run format"
|
|
31377
|
-
]
|
|
31378
|
-
}
|
|
31379
|
-
};
|
|
31380
|
-
|
|
31381
|
-
// src/server/BeansMcpServer.ts
|
|
31382
31800
|
var execFileAsync2 = promisify2(execFile2);
|
|
31383
31801
|
var PACKAGE_VERSION = package_default.version ?? "0.0.0-dev";
|
|
31802
|
+
var CLOSED_STATUSES = /* @__PURE__ */ new Set(["completed", "scrapped"]);
|
|
31803
|
+
var BEAN_ID_HINT = "Missing required field `beanId`. Did you mean `beanId`?";
|
|
31384
31804
|
function getSafeCliEnv(env) {
|
|
31385
31805
|
const whitelist = ["PATH", "HOME", "USER", "LANG", "LC_ALL", "LC_CTYPE", "SHELL"];
|
|
31386
31806
|
const safeEnv = {};
|
|
@@ -31401,7 +31821,8 @@ function extractVersionFromOutput(output) {
|
|
|
31401
31821
|
if (!trimmed) {
|
|
31402
31822
|
return null;
|
|
31403
31823
|
}
|
|
31404
|
-
const
|
|
31824
|
+
const versionRegex = /(?:^|[^\d])v?(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)/;
|
|
31825
|
+
const match = versionRegex.exec(trimmed);
|
|
31405
31826
|
return match?.[1] ?? null;
|
|
31406
31827
|
}
|
|
31407
31828
|
async function detectBeansCliVersion(cliPath, workspaceRoot) {
|
|
@@ -31418,10 +31839,10 @@ ${stderr}`);
|
|
|
31418
31839
|
return null;
|
|
31419
31840
|
}
|
|
31420
31841
|
}
|
|
31421
|
-
async function getBeanById(backend, beanId) {
|
|
31842
|
+
async function getBeanById(backend, beanId, beans) {
|
|
31422
31843
|
try {
|
|
31423
|
-
const
|
|
31424
|
-
const found =
|
|
31844
|
+
const allBeans = beans ?? await backend.list();
|
|
31845
|
+
const found = allBeans.find((b) => b.id === beanId);
|
|
31425
31846
|
if (!found) {
|
|
31426
31847
|
throw new Error(`Bean not found: ${beanId}`);
|
|
31427
31848
|
}
|
|
@@ -31430,12 +31851,111 @@ async function getBeanById(backend, beanId) {
|
|
|
31430
31851
|
throw new Error(`Failed to fetch bean ${beanId}: ${error48.message}`);
|
|
31431
31852
|
}
|
|
31432
31853
|
}
|
|
31854
|
+
function collectDescendantBeans(beans, rootBeanId) {
|
|
31855
|
+
const byParent = /* @__PURE__ */ new Map();
|
|
31856
|
+
const byId = new Map(beans.map((bean) => [bean.id, bean]));
|
|
31857
|
+
for (const bean of beans) {
|
|
31858
|
+
if (!bean.parentId) {
|
|
31859
|
+
continue;
|
|
31860
|
+
}
|
|
31861
|
+
const children = byParent.get(bean.parentId) ?? [];
|
|
31862
|
+
children.push(bean.id);
|
|
31863
|
+
byParent.set(bean.parentId, children);
|
|
31864
|
+
}
|
|
31865
|
+
const queue = [...byParent.get(rootBeanId) ?? []];
|
|
31866
|
+
const visited = /* @__PURE__ */ new Set();
|
|
31867
|
+
const descendants = [];
|
|
31868
|
+
while (queue.length > 0) {
|
|
31869
|
+
const currentId = queue.shift();
|
|
31870
|
+
if (!currentId || visited.has(currentId)) {
|
|
31871
|
+
continue;
|
|
31872
|
+
}
|
|
31873
|
+
visited.add(currentId);
|
|
31874
|
+
const currentBean = byId.get(currentId);
|
|
31875
|
+
if (!currentBean) {
|
|
31876
|
+
continue;
|
|
31877
|
+
}
|
|
31878
|
+
descendants.push(currentBean);
|
|
31879
|
+
const children = byParent.get(currentId);
|
|
31880
|
+
if (children && children.length > 0) {
|
|
31881
|
+
queue.push(...children);
|
|
31882
|
+
}
|
|
31883
|
+
}
|
|
31884
|
+
return descendants;
|
|
31885
|
+
}
|
|
31886
|
+
async function cascadeStatusToDescendants(backend, rootBeanId, targetStatus, options) {
|
|
31887
|
+
const beans = options?.beans ?? await backend.list();
|
|
31888
|
+
const descendants = collectDescendantBeans(beans, rootBeanId);
|
|
31889
|
+
const updatedBeanIds = [];
|
|
31890
|
+
const skippedBeanIds = [];
|
|
31891
|
+
const errors = [];
|
|
31892
|
+
const toUpdate = [];
|
|
31893
|
+
for (const bean of descendants) {
|
|
31894
|
+
if (options?.onlyCurrentStatuses && !options.onlyCurrentStatuses.has(bean.status)) {
|
|
31895
|
+
skippedBeanIds.push(bean.id);
|
|
31896
|
+
continue;
|
|
31897
|
+
}
|
|
31898
|
+
toUpdate.push(bean);
|
|
31899
|
+
}
|
|
31900
|
+
const settled = await Promise.allSettled(
|
|
31901
|
+
toUpdate.map(async (bean) => backend.update(bean.id, { status: targetStatus }))
|
|
31902
|
+
);
|
|
31903
|
+
settled.forEach((result, index) => {
|
|
31904
|
+
const bean = toUpdate[index];
|
|
31905
|
+
if (!bean) {
|
|
31906
|
+
return;
|
|
31907
|
+
}
|
|
31908
|
+
if (result.status === "fulfilled") {
|
|
31909
|
+
updatedBeanIds.push(bean.id);
|
|
31910
|
+
return;
|
|
31911
|
+
}
|
|
31912
|
+
errors.push({
|
|
31913
|
+
beanId: bean.id,
|
|
31914
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason)
|
|
31915
|
+
});
|
|
31916
|
+
});
|
|
31917
|
+
return {
|
|
31918
|
+
totalDescendants: descendants.length,
|
|
31919
|
+
updatedBeanIds,
|
|
31920
|
+
skippedBeanIds,
|
|
31921
|
+
errors
|
|
31922
|
+
};
|
|
31923
|
+
}
|
|
31924
|
+
function completeMarkdownTasks(body) {
|
|
31925
|
+
const lines = body.split(/\r?\n/);
|
|
31926
|
+
let totalTaskCount = 0;
|
|
31927
|
+
let updatedTaskCount = 0;
|
|
31928
|
+
const taskLinePattern = /^\s*(?:[-*+]|\d+\.)\s+\[[ xX]\]/;
|
|
31929
|
+
const uncheckedTaskLinePattern = /^(\s*(?:[-*+]|\d+\.)\s+\[)\s(\].*)$/;
|
|
31930
|
+
const nextLines = lines.map((line) => {
|
|
31931
|
+
if (!taskLinePattern.test(line)) {
|
|
31932
|
+
return line;
|
|
31933
|
+
}
|
|
31934
|
+
totalTaskCount += 1;
|
|
31935
|
+
const uncheckedMatch = uncheckedTaskLinePattern.exec(line);
|
|
31936
|
+
if (!uncheckedMatch) {
|
|
31937
|
+
return line;
|
|
31938
|
+
}
|
|
31939
|
+
updatedTaskCount += 1;
|
|
31940
|
+
return `${uncheckedMatch[1]}x${uncheckedMatch[2]}`;
|
|
31941
|
+
});
|
|
31942
|
+
const nextBody = nextLines.join("\n");
|
|
31943
|
+
return { nextBody, totalTaskCount, updatedTaskCount };
|
|
31944
|
+
}
|
|
31433
31945
|
function initHandler(backend) {
|
|
31434
31946
|
return async ({ prefix }) => {
|
|
31435
31947
|
const result = await backend.init(prefix);
|
|
31436
31948
|
return makeTextAndStructured(result);
|
|
31437
31949
|
};
|
|
31438
31950
|
}
|
|
31951
|
+
function archiveHandler(backend) {
|
|
31952
|
+
return async () => {
|
|
31953
|
+
if (typeof backend.archive !== "function") {
|
|
31954
|
+
throw new TypeError("Archive is not supported by the current backend");
|
|
31955
|
+
}
|
|
31956
|
+
return makeTextAndStructured(await backend.archive());
|
|
31957
|
+
};
|
|
31958
|
+
}
|
|
31439
31959
|
function viewHandler(backend) {
|
|
31440
31960
|
return async ({ beanId, beanIds }) => {
|
|
31441
31961
|
const ids = Array.isArray(beanIds) && beanIds.length > 0 ? beanIds : beanId ? [beanId] : [];
|
|
@@ -31450,7 +31970,12 @@ function viewHandler(backend) {
|
|
|
31450
31970
|
const byId = new Map(beans.map((b) => [b.id, b]));
|
|
31451
31971
|
const found = ids.map((id) => byId.get(id)).filter(Boolean);
|
|
31452
31972
|
const missingBeanIds = ids.filter((id) => !byId.has(id));
|
|
31453
|
-
return makeTextAndStructured({
|
|
31973
|
+
return makeTextAndStructured({
|
|
31974
|
+
beans: found,
|
|
31975
|
+
missingBeanIds,
|
|
31976
|
+
count: found.length,
|
|
31977
|
+
requestedCount: ids.length
|
|
31978
|
+
});
|
|
31454
31979
|
};
|
|
31455
31980
|
}
|
|
31456
31981
|
async function checkVersionCompatibility(cliPath, workspaceRoot, detector) {
|
|
@@ -31468,7 +31993,14 @@ async function checkVersionCompatibility(cliPath, workspaceRoot, detector) {
|
|
|
31468
31993
|
}
|
|
31469
31994
|
}
|
|
31470
31995
|
function createHandler(backend) {
|
|
31471
|
-
return async (input) =>
|
|
31996
|
+
return async (input) => {
|
|
31997
|
+
const bean = await backend.create(input);
|
|
31998
|
+
const warnings = input.description !== void 0 ? ["`description` is deprecated; use `body` instead."] : void 0;
|
|
31999
|
+
return makeTextAndStructured({
|
|
32000
|
+
bean,
|
|
32001
|
+
...warnings ? { warnings } : {}
|
|
32002
|
+
});
|
|
32003
|
+
};
|
|
31472
32004
|
}
|
|
31473
32005
|
function editHandler(backend) {
|
|
31474
32006
|
return async ({
|
|
@@ -31482,18 +32014,30 @@ function reopenHandler(backend) {
|
|
|
31482
32014
|
requiredCurrentStatus,
|
|
31483
32015
|
targetStatus
|
|
31484
32016
|
}) => {
|
|
31485
|
-
const
|
|
31486
|
-
|
|
31487
|
-
|
|
32017
|
+
const beans = await backend.list();
|
|
32018
|
+
const bean = await getBeanById(backend, beanId, beans);
|
|
32019
|
+
if (bean.status === requiredCurrentStatus) {
|
|
32020
|
+
const updatedParentBean = await backend.update(beanId, { status: targetStatus });
|
|
32021
|
+
const cascade = await cascadeStatusToDescendants(backend, beanId, targetStatus, {
|
|
32022
|
+
onlyCurrentStatuses: CLOSED_STATUSES,
|
|
32023
|
+
beans
|
|
32024
|
+
});
|
|
32025
|
+
return makeTextAndStructured({
|
|
32026
|
+
bean: updatedParentBean,
|
|
32027
|
+
cascade: {
|
|
32028
|
+
totalDescendants: cascade.totalDescendants,
|
|
32029
|
+
updatedBeanIds: cascade.updatedBeanIds,
|
|
32030
|
+
skippedBeanIds: cascade.skippedBeanIds,
|
|
32031
|
+
errors: cascade.errors
|
|
32032
|
+
}
|
|
32033
|
+
});
|
|
31488
32034
|
}
|
|
31489
|
-
|
|
31490
|
-
bean: await backend.update(beanId, { status: targetStatus })
|
|
31491
|
-
});
|
|
32035
|
+
throw new Error(`Bean ${beanId} is not ${requiredCurrentStatus}`);
|
|
31492
32036
|
};
|
|
31493
32037
|
}
|
|
31494
32038
|
function updateHandler(backend) {
|
|
31495
|
-
return async (input) =>
|
|
31496
|
-
|
|
32039
|
+
return async (input) => {
|
|
32040
|
+
const updatedBean = await backend.update(input.beanId, {
|
|
31497
32041
|
status: input.status,
|
|
31498
32042
|
type: input.type,
|
|
31499
32043
|
priority: input.priority,
|
|
@@ -31505,8 +32049,37 @@ function updateHandler(backend) {
|
|
|
31505
32049
|
bodyAppend: input.bodyAppend,
|
|
31506
32050
|
bodyReplace: input.bodyReplace,
|
|
31507
32051
|
ifMatch: input.ifMatch
|
|
31508
|
-
})
|
|
31509
|
-
|
|
32052
|
+
});
|
|
32053
|
+
const closeStatus = input.status;
|
|
32054
|
+
const shouldCascadeClose = Boolean(closeStatus && CLOSED_STATUSES.has(closeStatus));
|
|
32055
|
+
const cascade = shouldCascadeClose ? await cascadeStatusToDescendants(backend, input.beanId, closeStatus, {
|
|
32056
|
+
beans: await backend.list()
|
|
32057
|
+
}) : null;
|
|
32058
|
+
return makeTextAndStructured({
|
|
32059
|
+
bean: updatedBean,
|
|
32060
|
+
...cascade ? {
|
|
32061
|
+
cascade: {
|
|
32062
|
+
totalDescendants: cascade.totalDescendants,
|
|
32063
|
+
updatedBeanIds: cascade.updatedBeanIds,
|
|
32064
|
+
skippedBeanIds: cascade.skippedBeanIds,
|
|
32065
|
+
errors: cascade.errors
|
|
32066
|
+
}
|
|
32067
|
+
} : {}
|
|
32068
|
+
});
|
|
32069
|
+
};
|
|
32070
|
+
}
|
|
32071
|
+
function completeTasksHandler(backend) {
|
|
32072
|
+
return async ({ beanId }) => {
|
|
32073
|
+
const bean = await getBeanById(backend, beanId);
|
|
32074
|
+
const { nextBody, totalTaskCount, updatedTaskCount } = completeMarkdownTasks(bean.body || "");
|
|
32075
|
+
const updatedBean = updatedTaskCount > 0 ? await backend.update(beanId, { body: nextBody }) : bean;
|
|
32076
|
+
return makeTextAndStructured({
|
|
32077
|
+
bean: updatedBean,
|
|
32078
|
+
totalTaskCount,
|
|
32079
|
+
updatedTaskCount,
|
|
32080
|
+
unchangedTaskCount: totalTaskCount - updatedTaskCount
|
|
32081
|
+
});
|
|
32082
|
+
};
|
|
31510
32083
|
}
|
|
31511
32084
|
function deleteHandler(backend) {
|
|
31512
32085
|
return async ({ beanId, beanIds, force }) => {
|
|
@@ -31542,7 +32115,11 @@ function deleteHandler(backend) {
|
|
|
31542
32115
|
await backend.delete(id);
|
|
31543
32116
|
results.push({ beanId: id, deleted: true });
|
|
31544
32117
|
} catch (error48) {
|
|
31545
|
-
results.push({
|
|
32118
|
+
results.push({
|
|
32119
|
+
beanId: id,
|
|
32120
|
+
deleted: false,
|
|
32121
|
+
error: error48.message
|
|
32122
|
+
});
|
|
31546
32123
|
}
|
|
31547
32124
|
}
|
|
31548
32125
|
return makeTextAndStructured({
|
|
@@ -31553,15 +32130,53 @@ function deleteHandler(backend) {
|
|
|
31553
32130
|
});
|
|
31554
32131
|
};
|
|
31555
32132
|
}
|
|
32133
|
+
function bulkCreateHandler(backend) {
|
|
32134
|
+
return async (input) => {
|
|
32135
|
+
const results = await backend.bulkCreate(input.beans, input.parent);
|
|
32136
|
+
const deprecatedDescriptionCount = input.beans.filter((bean) => bean.description !== void 0).length;
|
|
32137
|
+
return makeTextAndStructured({
|
|
32138
|
+
results,
|
|
32139
|
+
requestedCount: input.beans.length,
|
|
32140
|
+
successCount: results.filter((r) => r.bean).length,
|
|
32141
|
+
failedCount: results.filter((r) => r.error).length,
|
|
32142
|
+
...deprecatedDescriptionCount > 0 ? {
|
|
32143
|
+
warnings: [
|
|
32144
|
+
`Found ${deprecatedDescriptionCount} bean(s) using deprecated field \`description\`; use \`body\` instead.`
|
|
32145
|
+
]
|
|
32146
|
+
} : {}
|
|
32147
|
+
});
|
|
32148
|
+
};
|
|
32149
|
+
}
|
|
32150
|
+
function bulkUpdateHandler(backend) {
|
|
32151
|
+
return async (input) => {
|
|
32152
|
+
const results = await backend.bulkUpdate(input.beans, input.parent);
|
|
32153
|
+
return makeTextAndStructured({
|
|
32154
|
+
results,
|
|
32155
|
+
requestedCount: input.beans.length,
|
|
32156
|
+
successCount: results.filter((r) => r.bean).length,
|
|
32157
|
+
failedCount: results.filter((r) => r.error).length
|
|
32158
|
+
});
|
|
32159
|
+
};
|
|
32160
|
+
}
|
|
31556
32161
|
function queryHandler(backend) {
|
|
31557
|
-
return async (opts) =>
|
|
32162
|
+
return async (opts) => {
|
|
32163
|
+
if (opts.operation === "graphql") {
|
|
32164
|
+
if (typeof backend.queryGraphql !== "function") {
|
|
32165
|
+
throw new TypeError("GraphQL passthrough is not supported by the current backend");
|
|
32166
|
+
}
|
|
32167
|
+
const result = await backend.queryGraphql(opts.graphql || "", opts.variables);
|
|
32168
|
+
return makeTextAndStructured({ data: result.data, errors: result.errors ?? [] });
|
|
32169
|
+
}
|
|
32170
|
+
return handleQueryOperation(backend, opts);
|
|
32171
|
+
};
|
|
31558
32172
|
}
|
|
31559
32173
|
function beanFileHandler(backend) {
|
|
31560
32174
|
return async ({
|
|
31561
32175
|
operation,
|
|
31562
32176
|
path,
|
|
31563
32177
|
content,
|
|
31564
|
-
overwrite
|
|
32178
|
+
overwrite,
|
|
32179
|
+
fields
|
|
31565
32180
|
}) => {
|
|
31566
32181
|
if (operation === "read") {
|
|
31567
32182
|
return makeTextAndStructured(await backend.readBeanFile(path));
|
|
@@ -31572,6 +32187,9 @@ function beanFileHandler(backend) {
|
|
|
31572
32187
|
if (operation === "create") {
|
|
31573
32188
|
return makeTextAndStructured(await backend.createBeanFile(path, content || "", { overwrite }));
|
|
31574
32189
|
}
|
|
32190
|
+
if (operation === "update_frontmatter") {
|
|
32191
|
+
return makeTextAndStructured(await backend.updateBeanFrontmatter(path, fields || {}));
|
|
32192
|
+
}
|
|
31575
32193
|
if (operation === "delete") {
|
|
31576
32194
|
return makeTextAndStructured(await backend.deleteBeanFile(path));
|
|
31577
32195
|
}
|
|
@@ -31606,6 +32224,21 @@ function registerTools(server, backend) {
|
|
|
31606
32224
|
},
|
|
31607
32225
|
initHandler(backend)
|
|
31608
32226
|
);
|
|
32227
|
+
server.registerTool(
|
|
32228
|
+
"beans_archive",
|
|
32229
|
+
{
|
|
32230
|
+
title: "Archive Beans",
|
|
32231
|
+
description: "Archive completed or scrapped beans, equivalent to the beans CLI archive command.",
|
|
32232
|
+
inputSchema: external_exports3.object({}),
|
|
32233
|
+
annotations: {
|
|
32234
|
+
readOnlyHint: false,
|
|
32235
|
+
destructiveHint: false,
|
|
32236
|
+
idempotentHint: false,
|
|
32237
|
+
openWorldHint: false
|
|
32238
|
+
}
|
|
32239
|
+
},
|
|
32240
|
+
archiveHandler(backend)
|
|
32241
|
+
);
|
|
31609
32242
|
server.registerTool(
|
|
31610
32243
|
"beans_view",
|
|
31611
32244
|
{
|
|
@@ -31615,7 +32248,7 @@ function registerTools(server, backend) {
|
|
|
31615
32248
|
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
31616
32249
|
beanIds: external_exports3.array(external_exports3.string().min(1).max(MAX_ID_LENGTH)).optional()
|
|
31617
32250
|
}).refine((input) => Boolean(input.beanId) || Array.isArray(input.beanIds) && input.beanIds.length > 0, {
|
|
31618
|
-
message:
|
|
32251
|
+
message: `Either beanId or beanIds must be provided. ${BEAN_ID_HINT}`
|
|
31619
32252
|
}),
|
|
31620
32253
|
annotations: {
|
|
31621
32254
|
readOnlyHint: true,
|
|
@@ -31636,7 +32269,8 @@ function registerTools(server, backend) {
|
|
|
31636
32269
|
type: external_exports3.string().min(1).max(MAX_METADATA_LENGTH),
|
|
31637
32270
|
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31638
32271
|
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31639
|
-
|
|
32272
|
+
body: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional().describe("Body markdown content"),
|
|
32273
|
+
description: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional().describe("Deprecated alias for body"),
|
|
31640
32274
|
parent: external_exports3.string().max(MAX_ID_LENGTH).optional()
|
|
31641
32275
|
}),
|
|
31642
32276
|
annotations: {
|
|
@@ -31654,7 +32288,7 @@ function registerTools(server, backend) {
|
|
|
31654
32288
|
title: "Edit Bean Metadata",
|
|
31655
32289
|
description: "Update bean metadata fields (status/type/priority/parent/blocking).",
|
|
31656
32290
|
inputSchema: external_exports3.object({
|
|
31657
|
-
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH),
|
|
32291
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
31658
32292
|
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31659
32293
|
type: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31660
32294
|
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
@@ -31662,7 +32296,11 @@ function registerTools(server, backend) {
|
|
|
31662
32296
|
clearParent: external_exports3.boolean().optional(),
|
|
31663
32297
|
blocking: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).optional(),
|
|
31664
32298
|
blockedBy: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).optional()
|
|
31665
|
-
}),
|
|
32299
|
+
}).superRefine((input, ctx) => {
|
|
32300
|
+
if (!input.beanId) {
|
|
32301
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["beanId"], message: BEAN_ID_HINT });
|
|
32302
|
+
}
|
|
32303
|
+
}).transform((input) => ({ ...input, beanId: input.beanId })),
|
|
31666
32304
|
annotations: {
|
|
31667
32305
|
readOnlyHint: false,
|
|
31668
32306
|
destructiveHint: false,
|
|
@@ -31678,10 +32316,14 @@ function registerTools(server, backend) {
|
|
|
31678
32316
|
title: "Reopen Bean",
|
|
31679
32317
|
description: "Reopen a completed or scrapped bean into a non-closed status.",
|
|
31680
32318
|
inputSchema: external_exports3.object({
|
|
31681
|
-
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH),
|
|
32319
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
31682
32320
|
requiredCurrentStatus: external_exports3.enum(["completed", "scrapped"]),
|
|
31683
32321
|
targetStatus: external_exports3.string().max(MAX_METADATA_LENGTH).default("todo")
|
|
31684
|
-
}),
|
|
32322
|
+
}).superRefine((input, ctx) => {
|
|
32323
|
+
if (!input.beanId) {
|
|
32324
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["beanId"], message: BEAN_ID_HINT });
|
|
32325
|
+
}
|
|
32326
|
+
}).transform((input) => ({ ...input, beanId: input.beanId })),
|
|
31685
32327
|
annotations: {
|
|
31686
32328
|
readOnlyHint: false,
|
|
31687
32329
|
destructiveHint: false,
|
|
@@ -31697,7 +32339,7 @@ function registerTools(server, backend) {
|
|
|
31697
32339
|
title: "Update Bean",
|
|
31698
32340
|
description: "Update bean metadata fields (status/type/priority/parent/blocking). Consolidated replacement for per-field update tools.",
|
|
31699
32341
|
inputSchema: external_exports3.object({
|
|
31700
|
-
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH),
|
|
32342
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
31701
32343
|
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31702
32344
|
type: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31703
32345
|
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
@@ -31714,12 +32356,16 @@ function registerTools(server, backend) {
|
|
|
31714
32356
|
})
|
|
31715
32357
|
).optional(),
|
|
31716
32358
|
ifMatch: external_exports3.string().max(MAX_METADATA_LENGTH).optional()
|
|
32359
|
+
}).superRefine((input, ctx) => {
|
|
32360
|
+
if (!input.beanId) {
|
|
32361
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["beanId"], message: BEAN_ID_HINT });
|
|
32362
|
+
}
|
|
31717
32363
|
}).refine(
|
|
31718
32364
|
(input) => !(input.body !== void 0 && (input.bodyAppend !== void 0 || input.bodyReplace !== void 0)),
|
|
31719
32365
|
{
|
|
31720
32366
|
message: "body cannot be combined with bodyAppend/bodyReplace"
|
|
31721
32367
|
}
|
|
31722
|
-
),
|
|
32368
|
+
).transform((input) => ({ ...input, beanId: input.beanId })),
|
|
31723
32369
|
annotations: {
|
|
31724
32370
|
readOnlyHint: false,
|
|
31725
32371
|
destructiveHint: false,
|
|
@@ -31739,7 +32385,7 @@ function registerTools(server, backend) {
|
|
|
31739
32385
|
beanIds: external_exports3.array(external_exports3.string().min(1).max(MAX_ID_LENGTH)).optional(),
|
|
31740
32386
|
force: external_exports3.boolean().default(false)
|
|
31741
32387
|
}).refine((input) => Boolean(input.beanId) || Array.isArray(input.beanIds) && input.beanIds.length > 0, {
|
|
31742
|
-
message:
|
|
32388
|
+
message: `Either beanId or beanIds must be provided. ${BEAN_ID_HINT}`
|
|
31743
32389
|
}),
|
|
31744
32390
|
annotations: {
|
|
31745
32391
|
readOnlyHint: false,
|
|
@@ -31750,25 +32396,122 @@ function registerTools(server, backend) {
|
|
|
31750
32396
|
},
|
|
31751
32397
|
deleteHandler(backend)
|
|
31752
32398
|
);
|
|
32399
|
+
const beanCreateItemSchema = external_exports3.object({
|
|
32400
|
+
title: external_exports3.string().min(1).max(MAX_TITLE_LENGTH),
|
|
32401
|
+
type: external_exports3.string().min(1).max(MAX_METADATA_LENGTH),
|
|
32402
|
+
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32403
|
+
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32404
|
+
body: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional().describe("Body markdown content"),
|
|
32405
|
+
description: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional().describe("Deprecated alias for body"),
|
|
32406
|
+
parent: external_exports3.string().max(MAX_ID_LENGTH).optional().describe("Override the top-level parent for this item")
|
|
32407
|
+
});
|
|
32408
|
+
server.registerTool(
|
|
32409
|
+
"beans_bulk_create",
|
|
32410
|
+
{
|
|
32411
|
+
title: "Bulk Create Beans",
|
|
32412
|
+
description: "Create multiple beans in one call. Optionally assign all of them (or a subset) to a shared parent.",
|
|
32413
|
+
inputSchema: external_exports3.object({
|
|
32414
|
+
beans: external_exports3.array(beanCreateItemSchema).min(1),
|
|
32415
|
+
parent: external_exports3.string().max(MAX_ID_LENGTH).optional().describe("Default parent ID applied to any bean that does not specify its own parent")
|
|
32416
|
+
}),
|
|
32417
|
+
annotations: {
|
|
32418
|
+
readOnlyHint: false,
|
|
32419
|
+
destructiveHint: false,
|
|
32420
|
+
idempotentHint: false,
|
|
32421
|
+
openWorldHint: false
|
|
32422
|
+
}
|
|
32423
|
+
},
|
|
32424
|
+
bulkCreateHandler(backend)
|
|
32425
|
+
);
|
|
32426
|
+
const beanUpdateItemSchema = external_exports3.object({
|
|
32427
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
32428
|
+
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32429
|
+
type: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32430
|
+
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32431
|
+
parent: external_exports3.string().max(MAX_ID_LENGTH).optional().describe("Override the top-level parent for this item"),
|
|
32432
|
+
clearParent: external_exports3.boolean().optional(),
|
|
32433
|
+
blocking: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).optional(),
|
|
32434
|
+
blockedBy: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).optional(),
|
|
32435
|
+
body: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
32436
|
+
bodyAppend: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
32437
|
+
bodyReplace: external_exports3.array(external_exports3.object({ old: external_exports3.string().max(MAX_DESCRIPTION_LENGTH), new: external_exports3.string().max(MAX_DESCRIPTION_LENGTH) })).optional(),
|
|
32438
|
+
ifMatch: external_exports3.string().max(MAX_METADATA_LENGTH).optional()
|
|
32439
|
+
}).superRefine((input, ctx) => {
|
|
32440
|
+
if (!input.beanId) {
|
|
32441
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["beanId"], message: BEAN_ID_HINT });
|
|
32442
|
+
}
|
|
32443
|
+
}).refine(
|
|
32444
|
+
(input) => !(input.body !== void 0 && (input.bodyAppend !== void 0 || input.bodyReplace !== void 0)),
|
|
32445
|
+
{ message: "body cannot be combined with bodyAppend/bodyReplace" }
|
|
32446
|
+
).transform((input) => ({ ...input, beanId: input.beanId }));
|
|
32447
|
+
server.registerTool(
|
|
32448
|
+
"beans_bulk_update",
|
|
32449
|
+
{
|
|
32450
|
+
title: "Bulk Update Beans",
|
|
32451
|
+
description: "Update multiple beans in one call. Optionally assign all of them (or a subset) to a shared parent.",
|
|
32452
|
+
inputSchema: external_exports3.object({
|
|
32453
|
+
beans: external_exports3.array(beanUpdateItemSchema).min(1),
|
|
32454
|
+
parent: external_exports3.string().max(MAX_ID_LENGTH).optional().describe("Default parent ID applied to any bean that does not specify its own parent")
|
|
32455
|
+
}),
|
|
32456
|
+
annotations: {
|
|
32457
|
+
readOnlyHint: false,
|
|
32458
|
+
destructiveHint: false,
|
|
32459
|
+
idempotentHint: false,
|
|
32460
|
+
openWorldHint: false
|
|
32461
|
+
}
|
|
32462
|
+
},
|
|
32463
|
+
bulkUpdateHandler(backend)
|
|
32464
|
+
);
|
|
32465
|
+
server.registerTool(
|
|
32466
|
+
"beans_complete_tasks",
|
|
32467
|
+
{
|
|
32468
|
+
title: "Complete Markdown Tasks",
|
|
32469
|
+
description: "Mark all markdown checklist tasks within a bean as completed.",
|
|
32470
|
+
inputSchema: external_exports3.object({
|
|
32471
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional()
|
|
32472
|
+
}).superRefine((input, ctx) => {
|
|
32473
|
+
if (!input.beanId) {
|
|
32474
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["beanId"], message: BEAN_ID_HINT });
|
|
32475
|
+
}
|
|
32476
|
+
}).transform((input) => ({ ...input, beanId: input.beanId })),
|
|
32477
|
+
annotations: {
|
|
32478
|
+
readOnlyHint: false,
|
|
32479
|
+
destructiveHint: false,
|
|
32480
|
+
idempotentHint: true,
|
|
32481
|
+
openWorldHint: false
|
|
32482
|
+
}
|
|
32483
|
+
},
|
|
32484
|
+
completeTasksHandler(backend)
|
|
32485
|
+
);
|
|
31753
32486
|
server.registerTool(
|
|
31754
32487
|
"beans_query",
|
|
31755
32488
|
{
|
|
31756
32489
|
title: "Query Beans",
|
|
31757
32490
|
description: "Unified query tool for refresh, filter, search, and sort operations.",
|
|
31758
32491
|
inputSchema: external_exports3.object({
|
|
31759
|
-
operation: external_exports3.enum(["refresh", "filter", "search", "sort", "ready", "llm_context", "open_config"]).default("refresh"),
|
|
32492
|
+
operation: external_exports3.enum(["refresh", "filter", "search", "sort", "ready", "llm_context", "open_config", "graphql"]).default("refresh"),
|
|
31760
32493
|
mode: external_exports3.enum(["status-priority-type-title", "updated", "created", "id"]).optional(),
|
|
31761
32494
|
statuses: external_exports3.array(external_exports3.string().max(MAX_METADATA_LENGTH)).nullable().optional(),
|
|
31762
32495
|
types: external_exports3.array(external_exports3.string().max(MAX_METADATA_LENGTH)).nullable().optional(),
|
|
31763
32496
|
search: external_exports3.string().max(MAX_TITLE_LENGTH).optional(),
|
|
31764
32497
|
includeClosed: external_exports3.boolean().optional(),
|
|
31765
32498
|
tags: external_exports3.array(external_exports3.string().max(MAX_METADATA_LENGTH)).nullable().optional(),
|
|
32499
|
+
graphql: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
32500
|
+
variables: external_exports3.record(external_exports3.string(), external_exports3.unknown()).optional(),
|
|
31766
32501
|
writeToWorkspaceInstructions: external_exports3.boolean().optional()
|
|
32502
|
+
}).superRefine((input, ctx) => {
|
|
32503
|
+
if (input.operation === "graphql" && (!input.graphql || input.graphql.trim().length === 0)) {
|
|
32504
|
+
ctx.addIssue({
|
|
32505
|
+
code: external_exports3.ZodIssueCode.custom,
|
|
32506
|
+
path: ["graphql"],
|
|
32507
|
+
message: "graphql query string is required when operation is graphql"
|
|
32508
|
+
});
|
|
32509
|
+
}
|
|
31767
32510
|
}),
|
|
31768
32511
|
annotations: {
|
|
31769
|
-
readOnlyHint:
|
|
32512
|
+
readOnlyHint: false,
|
|
31770
32513
|
destructiveHint: false,
|
|
31771
|
-
idempotentHint:
|
|
32514
|
+
idempotentHint: false,
|
|
31772
32515
|
openWorldHint: false
|
|
31773
32516
|
}
|
|
31774
32517
|
},
|
|
@@ -31780,10 +32523,33 @@ function registerTools(server, backend) {
|
|
|
31780
32523
|
title: "Bean File Operations",
|
|
31781
32524
|
description: "Read, create, edit, or delete files under .beans (operation param).",
|
|
31782
32525
|
inputSchema: external_exports3.object({
|
|
31783
|
-
operation: external_exports3.enum(["read", "edit", "create", "delete"]),
|
|
32526
|
+
operation: external_exports3.enum(["read", "edit", "create", "delete", "update_frontmatter"]),
|
|
31784
32527
|
path: external_exports3.string().min(1).max(MAX_PATH_LENGTH),
|
|
31785
32528
|
content: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
31786
|
-
overwrite: external_exports3.boolean().optional()
|
|
32529
|
+
overwrite: external_exports3.boolean().optional(),
|
|
32530
|
+
fields: external_exports3.object({
|
|
32531
|
+
title: external_exports3.string().max(MAX_TITLE_LENGTH).optional(),
|
|
32532
|
+
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32533
|
+
type: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32534
|
+
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32535
|
+
parent_id: external_exports3.string().max(MAX_ID_LENGTH).nullable().optional(),
|
|
32536
|
+
tags: external_exports3.array(external_exports3.string().max(MAX_METADATA_LENGTH)).nullable().optional(),
|
|
32537
|
+
blocking_ids: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).nullable().optional(),
|
|
32538
|
+
blocked_by_ids: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).nullable().optional(),
|
|
32539
|
+
pr: external_exports3.string().max(MAX_TITLE_LENGTH).nullable().optional(),
|
|
32540
|
+
branch: external_exports3.string().max(MAX_TITLE_LENGTH).nullable().optional()
|
|
32541
|
+
}).optional()
|
|
32542
|
+
}).superRefine((input, ctx) => {
|
|
32543
|
+
if (input.operation === "update_frontmatter") {
|
|
32544
|
+
const fieldCount = Object.values(input.fields || {}).filter((value) => value !== void 0).length;
|
|
32545
|
+
if (fieldCount === 0) {
|
|
32546
|
+
ctx.addIssue({
|
|
32547
|
+
code: external_exports3.ZodIssueCode.custom,
|
|
32548
|
+
path: ["fields"],
|
|
32549
|
+
message: "At least one frontmatter field update is required"
|
|
32550
|
+
});
|
|
32551
|
+
}
|
|
32552
|
+
}
|
|
31787
32553
|
}),
|
|
31788
32554
|
annotations: {
|
|
31789
32555
|
readOnlyHint: false,
|
|
@@ -31823,6 +32589,18 @@ var MutableBackend = class {
|
|
|
31823
32589
|
init(prefix) {
|
|
31824
32590
|
return this.inner.init(prefix);
|
|
31825
32591
|
}
|
|
32592
|
+
archive() {
|
|
32593
|
+
if (typeof this.inner.archive === "function") {
|
|
32594
|
+
return this.inner.archive();
|
|
32595
|
+
}
|
|
32596
|
+
throw new TypeError("Archive is not supported by backend");
|
|
32597
|
+
}
|
|
32598
|
+
queryGraphql(query, variables) {
|
|
32599
|
+
if (typeof this.inner.queryGraphql === "function") {
|
|
32600
|
+
return this.inner.queryGraphql(query, variables);
|
|
32601
|
+
}
|
|
32602
|
+
throw new TypeError("GraphQL passthrough is not supported by backend");
|
|
32603
|
+
}
|
|
31826
32604
|
list(opts) {
|
|
31827
32605
|
return this.inner.list(opts);
|
|
31828
32606
|
}
|
|
@@ -31835,6 +32613,12 @@ var MutableBackend = class {
|
|
|
31835
32613
|
delete(id) {
|
|
31836
32614
|
return this.inner.delete(id);
|
|
31837
32615
|
}
|
|
32616
|
+
bulkCreate(beans, defaultParent) {
|
|
32617
|
+
return this.inner.bulkCreate(beans, defaultParent);
|
|
32618
|
+
}
|
|
32619
|
+
bulkUpdate(beans, defaultParent) {
|
|
32620
|
+
return this.inner.bulkUpdate(beans, defaultParent);
|
|
32621
|
+
}
|
|
31838
32622
|
openConfig() {
|
|
31839
32623
|
return this.inner.openConfig();
|
|
31840
32624
|
}
|
|
@@ -31856,6 +32640,9 @@ var MutableBackend = class {
|
|
|
31856
32640
|
editBeanFile(path, content) {
|
|
31857
32641
|
return this.inner.editBeanFile(path, content);
|
|
31858
32642
|
}
|
|
32643
|
+
updateBeanFrontmatter(path, updates) {
|
|
32644
|
+
return this.inner.updateBeanFrontmatter(path, updates);
|
|
32645
|
+
}
|
|
31859
32646
|
createBeanFile(path, content, opts) {
|
|
31860
32647
|
return this.inner.createBeanFile(path, content, opts);
|
|
31861
32648
|
}
|
|
@@ -31922,6 +32709,16 @@ function parseCliArgs(argv) {
|
|
|
31922
32709
|
const envPort = Number.parseInt(process.env.BEANS_VSCODE_MCP_PORT || process.env.BEANS_MCP_PORT || "", 10);
|
|
31923
32710
|
let port = Number.isInteger(envPort) && envPort > 0 ? envPort : DEFAULT_MCP_PORT;
|
|
31924
32711
|
let logDir;
|
|
32712
|
+
const parseStrictPositiveInt = (raw, flagName) => {
|
|
32713
|
+
if (!/^\d+$/.test(raw)) {
|
|
32714
|
+
throw new Error(`Invalid value for ${flagName}: ${raw}`);
|
|
32715
|
+
}
|
|
32716
|
+
const parsed = Number.parseInt(raw, 10);
|
|
32717
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
32718
|
+
throw new Error(`Invalid value for ${flagName}: ${raw}`);
|
|
32719
|
+
}
|
|
32720
|
+
return parsed;
|
|
32721
|
+
};
|
|
31925
32722
|
for (let i = 0; i < argv.length; i += 1) {
|
|
31926
32723
|
const arg = argv[i];
|
|
31927
32724
|
if ((arg === "--workspace" || arg === "--workspace-root") && argv[i + 1]) {
|
|
@@ -31935,10 +32732,7 @@ function parseCliArgs(argv) {
|
|
|
31935
32732
|
}
|
|
31936
32733
|
i += 1;
|
|
31937
32734
|
} else if (arg === "--port" && argv[i + 1]) {
|
|
31938
|
-
|
|
31939
|
-
if (Number.isInteger(parsedPort) && parsedPort > 0) {
|
|
31940
|
-
port = parsedPort;
|
|
31941
|
-
}
|
|
32735
|
+
port = parseStrictPositiveInt(argv[i + 1], "--port");
|
|
31942
32736
|
i += 1;
|
|
31943
32737
|
} else if (arg === "--log-dir" && argv[i + 1]) {
|
|
31944
32738
|
logDir = argv[i + 1];
|
|
@@ -32001,6 +32795,7 @@ export {
|
|
|
32001
32795
|
DEFAULT_MCP_PORT,
|
|
32002
32796
|
MAX_ID_LENGTH,
|
|
32003
32797
|
MAX_METADATA_LENGTH,
|
|
32798
|
+
MAX_PATH_LENGTH,
|
|
32004
32799
|
MAX_TITLE_LENGTH,
|
|
32005
32800
|
createBeansMcpServer,
|
|
32006
32801
|
isPathWithinRoot,
|