diff --git a/index.ts b/index.ts index 300a1af..7328e9e 100644 --- a/index.ts +++ b/index.ts @@ -11,6 +11,7 @@ import { boardTools } from "./tools/boards.ts"; import { cardTools } from "./tools/cards.ts"; import { commentTools } from "./tools/comments.ts"; +import { fileTools } from "./tools/files.ts"; import { labelTools } from "./tools/labels.ts"; import { listTools } from "./tools/lists.ts"; import { meTools } from "./tools/me.ts"; @@ -32,6 +33,7 @@ const otperPlugin = { ...listTools(config), ...cardTools(config), ...commentTools(config), + ...fileTools(config), ...labelTools(config), ...teamTools(config), ...priorityTools(config), diff --git a/package-lock.json b/package-lock.json index a516936..5fa20ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@ssntpl/openclaw-otper", - "version": "0.1.3", + "version": "0.1.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@ssntpl/openclaw-otper", - "version": "0.1.3", + "version": "0.1.4", "license": "MIT", "dependencies": { - "@ssntpl/otper-cli": "^0.1.7" + "@ssntpl/otper-cli": "^0.1.8" }, "devDependencies": { "@types/node": "^20.16.10", @@ -446,9 +446,9 @@ } }, "node_modules/@ssntpl/otper-cli": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@ssntpl/otper-cli/-/otper-cli-0.1.7.tgz", - "integrity": "sha512-cPT4Z0MA6vdbYVxghRUaT9FSWqVc3iImBXnd8fpa9u6CqRKojfE3tZPrSFTfY4qbPrwSyJFA7WnK3KM/lALH9A==", + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@ssntpl/otper-cli/-/otper-cli-0.1.8.tgz", + "integrity": "sha512-0Ke26SF+h96akmdtd4L8smHNyFcBeYv2a+ajpQ8FRCHNFuIg/CYtIh5Ae+IZp7H8g6vKr9SmcTHvGz3Xx/XG8g==", "license": "MIT", "dependencies": { "@oclif/core": "^4.0.30", diff --git a/package.json b/package.json index e1ba26b..7bb7cf5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ssntpl/openclaw-otper", - "version": "0.1.3", + "version": "0.1.4", "description": "OpenClaw plugin for Otper boards (https://otper.com) — exposes Otper boards, lists, cards, labels, comments, and today's priorities as agent tools.", "author": "SSNTPL ", "license": "MIT", @@ -39,7 +39,7 @@ ] }, "dependencies": { - "@ssntpl/otper-cli": "^0.1.7" + "@ssntpl/otper-cli": "^0.1.8" }, "devDependencies": { "@types/node": "^20.16.10", diff --git a/tools/files.ts b/tools/files.ts new file mode 100644 index 0000000..fe420be --- /dev/null +++ b/tools/files.ts @@ -0,0 +1,98 @@ +import { files } from "@ssntpl/otper-cli"; +import { clientFor, json, PluginConfig } from "./shared.ts"; + +export function fileTools(config: PluginConfig) { + return [ + { + name: "otper_attach_file_to_card", + label: "Otper: attach file to card", + description: + "Upload a local file from disk and attach it to a card. Provide the absolute path to the file and the target card id. MIME type is detected from the extension; override with mimeType if needed.", + parameters: { + type: "object", + properties: { + cardId: { type: "string", description: "Card id to attach the file to." }, + filePath: { + type: "string", + description: "Absolute path to the file on the local filesystem.", + }, + filename: { + type: "string", + description: + "Optional: filename to send to the server. Defaults to the basename of filePath.", + }, + mimeType: { + type: "string", + description: + "Optional: override the MIME type (e.g. image/png). Detected from extension by default.", + }, + }, + required: ["cardId", "filePath"], + }, + execute: async ( + _id: string, + p: { + cardId: string; + filePath: string; + filename?: string; + mimeType?: string; + }, + ) => { + const client = clientFor(config); + return json( + await files.uploadFile(client, { + cardId: p.cardId, + filePath: p.filePath, + filename: p.filename, + mimeType: p.mimeType, + }), + ); + }, + }, + { + name: "otper_attach_file_to_comment", + label: "Otper: attach file to comment", + description: + "Upload a local file from disk and attach it to a comment. Both the comment id and the parent card id are required (Otper stores the file under the card).", + parameters: { + type: "object", + properties: { + commentId: { type: "string", description: "Comment id to attach the file to." }, + cardId: { + type: "string", + description: "Id of the card the comment belongs to.", + }, + filePath: { + type: "string", + description: "Absolute path to the file on the local filesystem.", + }, + filename: { type: "string", description: "Optional override filename." }, + mimeType: { type: "string", description: "Optional override MIME type." }, + }, + required: ["commentId", "cardId", "filePath"], + }, + execute: async ( + _id: string, + p: { + commentId: string; + cardId: string; + filePath: string; + filename?: string; + mimeType?: string; + }, + ) => { + const client = clientFor(config); + return json( + await files.uploadFile(client, { + cardId: p.cardId, + ownerType: "Comment", + ownerId: p.commentId, + filePath: p.filePath, + filename: p.filename, + mimeType: p.mimeType, + }), + ); + }, + }, + ]; +}