@nextclaw/ncp-agent-runtime 0.2.1 → 0.2.3

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.
Files changed (2) hide show
  1. package/dist/index.js +40 -1
  2. package/package.json +5 -3
package/dist/index.js CHANGED
@@ -9,6 +9,42 @@ function readOptionalString(value) {
9
9
  const trimmed = value.trim();
10
10
  return trimmed.length > 0 ? trimmed : null;
11
11
  }
12
+ function isRenderableImagePart(part) {
13
+ return part.type === "file" && typeof part.mimeType === "string" && part.mimeType.startsWith("image/") && (typeof part.url === "string" && part.url.trim().length > 0 || typeof part.contentBase64 === "string" && part.contentBase64.trim().length > 0);
14
+ }
15
+ function toOpenAIUserContent(parts) {
16
+ const content = [];
17
+ for (const part of parts) {
18
+ if (part.type === "text" && part.text.trim().length > 0) {
19
+ content.push({ type: "text", text: part.text });
20
+ continue;
21
+ }
22
+ if (part.type === "rich-text" && part.text.trim().length > 0) {
23
+ content.push({ type: "text", text: part.text });
24
+ continue;
25
+ }
26
+ if (!isRenderableImagePart(part)) {
27
+ continue;
28
+ }
29
+ const url = typeof part.url === "string" && part.url.trim().length > 0 ? part.url.trim() : `data:${part.mimeType};base64,${part.contentBase64?.trim() ?? ""}`;
30
+ content.push({
31
+ type: "image_url",
32
+ image_url: {
33
+ url
34
+ }
35
+ });
36
+ }
37
+ if (content.length === 0) {
38
+ return "";
39
+ }
40
+ if (content.length === 1 && content[0]?.type === "text") {
41
+ return content[0].text;
42
+ }
43
+ return content;
44
+ }
45
+ function isTextLikePart(part) {
46
+ return part.type === "text" || part.type === "rich-text";
47
+ }
12
48
  function mergeMessageAndRequestMetadata(input) {
13
49
  const messageMetadata = input.messages.slice().reverse().find((message) => isRecord(message.metadata))?.metadata;
14
50
  return {
@@ -34,7 +70,10 @@ function messageToOpenAI(msg) {
34
70
  const role = msg.role;
35
71
  const parts = msg.parts ?? [];
36
72
  if (role === "user" || role === "system") {
37
- const text = parts.filter((p) => p.type === "text").map((p) => p.text).join("");
73
+ if (role === "user") {
74
+ return [{ role, content: toOpenAIUserContent(parts) }];
75
+ }
76
+ const text = parts.filter(isTextLikePart).map((part) => part.text).join("");
38
77
  return [{ role, content: text }];
39
78
  }
40
79
  if (role === "assistant") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/ncp-agent-runtime",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "private": false,
5
5
  "description": "Default agent runtime implementation built on NCP interfaces.",
6
6
  "type": "module",
@@ -15,17 +15,19 @@
15
15
  "dist"
16
16
  ],
17
17
  "dependencies": {
18
- "@nextclaw/ncp": "0.3.1"
18
+ "@nextclaw/ncp": "0.3.2"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@types/node": "^20.17.6",
22
22
  "prettier": "^3.3.3",
23
23
  "tsup": "^8.3.5",
24
- "typescript": "^5.6.3"
24
+ "typescript": "^5.6.3",
25
+ "vitest": "^2.1.2"
25
26
  },
26
27
  "scripts": {
27
28
  "build": "tsup src/index.ts --format esm --dts --out-dir dist",
28
29
  "lint": "eslint .",
30
+ "test": "vitest run",
29
31
  "tsc": "tsc -p tsconfig.json"
30
32
  }
31
33
  }