129 lines
3.4 KiB
TypeScript
129 lines
3.4 KiB
TypeScript
// src/tools/memory/pin-remove.ts
|
|
// Copyright (C) 2025 DTP Technologies, LLC
|
|
// All Rights Reserved
|
|
|
|
import type { ToolDefinition } from "../../lib/ai-client.js";
|
|
|
|
import {
|
|
DtpTool,
|
|
type ToolArguments,
|
|
type ToolContext,
|
|
} from "../../lib/tool.js";
|
|
import { ChatSession, ChatSessionMode } from "../../models/chat-session.js";
|
|
|
|
export class PinRemoveTool extends DtpTool {
|
|
get name(): string {
|
|
return "PinRemoveTool";
|
|
}
|
|
get slug(): string {
|
|
return "pin-remove";
|
|
}
|
|
get metadata() {
|
|
return {
|
|
name: this.definition.function.name || "pin_remove",
|
|
category: "memory",
|
|
tags: ["pin", "pinboard", "note", "memory", "context", "remove"],
|
|
modes: [
|
|
ChatSessionMode.Plan,
|
|
ChatSessionMode.Build,
|
|
ChatSessionMode.Test,
|
|
ChatSessionMode.Ship,
|
|
ChatSessionMode.Develop,
|
|
],
|
|
};
|
|
}
|
|
|
|
public definition: ToolDefinition = {
|
|
type: "function",
|
|
function: {
|
|
name: "pin_remove",
|
|
description:
|
|
"Remove a pin from the session pinboard by its ID. Use this to free up space on the pinboard or remove information that is no longer relevant.",
|
|
parameters: {
|
|
type: "object",
|
|
properties: {
|
|
pin_id: {
|
|
type: "string",
|
|
description:
|
|
"The _id of the pin to remove. This is returned when the pin was added via pin_add, and is also visible in the PINBOARD section of the system prompt.",
|
|
},
|
|
},
|
|
required: ["pin_id"],
|
|
},
|
|
},
|
|
};
|
|
|
|
public async execute(
|
|
context: ToolContext,
|
|
args: ToolArguments,
|
|
): Promise<string> {
|
|
const pinId = args.pin_id as string | undefined;
|
|
|
|
if (!pinId || pinId.trim().length === 0) {
|
|
return this.error("INVALID_PARAMETER", "pin_id must not be empty.", {
|
|
parameter: "pin_id",
|
|
recoveryHint: "Provide the _id of the pin you want to remove.",
|
|
});
|
|
}
|
|
|
|
const sessionId = context.session._id.toHexString();
|
|
|
|
try {
|
|
const session = await ChatSession.findById(sessionId);
|
|
if (!session) {
|
|
return this.error("NOT_FOUND", `Session not found: ${sessionId}`);
|
|
}
|
|
|
|
const pinIndex = session.pins.findIndex(
|
|
(pin) => pin._id?.toString() === pinId,
|
|
);
|
|
|
|
if (pinIndex === -1) {
|
|
return this.error(
|
|
"NOT_FOUND",
|
|
`Pin not found: ${pinId}. Check the pin ID and try again.`,
|
|
{
|
|
recoveryHint:
|
|
"Pin IDs are shown in the PINBOARD section of the system prompt and returned when pins are added.",
|
|
},
|
|
);
|
|
}
|
|
|
|
const removedContent = session.pins[pinIndex]!.content;
|
|
session.pins.splice(pinIndex, 1);
|
|
await session.save();
|
|
|
|
const totalChars = session.pins.reduce(
|
|
(sum, pin) => sum + pin.content.length,
|
|
0,
|
|
);
|
|
|
|
return this.success(
|
|
{
|
|
pinId,
|
|
content: removedContent,
|
|
totalPins: session.pins.length,
|
|
totalChars,
|
|
maxChars: 8192,
|
|
},
|
|
`Pin removed from pinboard (${session.pins.length} pins remaining, ${totalChars}/8192 characters used).`,
|
|
);
|
|
} catch (error) {
|
|
const errorMessage =
|
|
error instanceof Error ? error.message : String(error);
|
|
|
|
this.log.error("Failed to remove pin", {
|
|
sessionId,
|
|
error: errorMessage,
|
|
});
|
|
|
|
return this.error(
|
|
"OPERATION_FAILED",
|
|
`Failed to remove pin: ${errorMessage}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
export default new PinRemoveTool();
|