poe-code 3.0.348 → 3.0.349
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/dist/index.js +51 -13
- package/dist/index.js.map +3 -3
- package/dist/metafile.json +1 -1
- package/dist/services/llm-client.js +54 -15
- package/dist/services/llm-client.js.map +1 -1
- package/package.json +1 -1
- package/packages/package-lint/dist/model.d.ts +1 -0
- package/packages/package-lint/dist/model.js +2 -1
- package/packages/package-lint/dist/rules/index.js +3 -1
- package/packages/package-lint/dist/rules/package-readme-required.d.ts +2 -0
- package/packages/package-lint/dist/rules/package-readme-required.js +21 -0
|
@@ -7,9 +7,9 @@ export function createPoeClient(options) {
|
|
|
7
7
|
const data = await requestCompletion(httpClient, options.baseUrl, options.apiKey, request);
|
|
8
8
|
return { content: extractTextContent(data) };
|
|
9
9
|
},
|
|
10
|
-
async media(
|
|
10
|
+
async media(type, request) {
|
|
11
11
|
const data = await requestCompletion(httpClient, options.baseUrl, options.apiKey, request);
|
|
12
|
-
return extractMediaFromCompletion(data);
|
|
12
|
+
return extractMediaFromCompletion(type, data);
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
15
|
}
|
|
@@ -80,7 +80,7 @@ function extractTextContent(data) {
|
|
|
80
80
|
return undefined;
|
|
81
81
|
return typeof message.content === "string" ? message.content : undefined;
|
|
82
82
|
}
|
|
83
|
-
function extractMediaFromCompletion(data) {
|
|
83
|
+
function extractMediaFromCompletion(type, data) {
|
|
84
84
|
const content = extractTextContent(data);
|
|
85
85
|
if (!content)
|
|
86
86
|
return {};
|
|
@@ -108,24 +108,63 @@ function extractMediaFromCompletion(data) {
|
|
|
108
108
|
if (isValidUrl(content.trim())) {
|
|
109
109
|
return { url: content.trim() };
|
|
110
110
|
}
|
|
111
|
-
// Try extracting
|
|
112
|
-
const markdownUrl =
|
|
111
|
+
// Try extracting media-specific markdown (e.g., "" or "[video](url)").
|
|
112
|
+
const markdownUrl = extractMarkdownMediaUrl(content, type);
|
|
113
113
|
if (markdownUrl) {
|
|
114
114
|
return { url: markdownUrl };
|
|
115
115
|
}
|
|
116
116
|
// No URL found, return content for error message
|
|
117
117
|
return { content };
|
|
118
118
|
}
|
|
119
|
-
function
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
119
|
+
function extractMarkdownMediaUrl(content, type) {
|
|
120
|
+
let searchFrom = 0;
|
|
121
|
+
while (searchFrom < content.length) {
|
|
122
|
+
const openLabel = content.indexOf("[", searchFrom);
|
|
123
|
+
if (openLabel === -1)
|
|
124
|
+
return undefined;
|
|
125
|
+
const closeLabel = content.indexOf("](", openLabel);
|
|
126
|
+
if (closeLabel === -1)
|
|
127
|
+
return undefined;
|
|
128
|
+
const urlStart = closeLabel + 2;
|
|
129
|
+
const urlEnd = content.indexOf(")", urlStart);
|
|
130
|
+
if (urlEnd === -1)
|
|
131
|
+
return undefined;
|
|
132
|
+
const label = content.slice(openLabel + 1, closeLabel);
|
|
133
|
+
const url = content.slice(urlStart, urlEnd);
|
|
134
|
+
const isImageMarkdown = openLabel > 0 && content[openLabel - 1] === "!";
|
|
135
|
+
if (isValidUrl(url) && isGeneratedMediaLabel(label, type, isImageMarkdown)) {
|
|
136
|
+
return url;
|
|
137
|
+
}
|
|
138
|
+
searchFrom = urlEnd + 1;
|
|
139
|
+
}
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
function isGeneratedMediaLabel(label, type, isImageMarkdown) {
|
|
143
|
+
if (type === "image" && isImageMarkdown) {
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
return labelTokens(label).includes(type);
|
|
147
|
+
}
|
|
148
|
+
function labelTokens(label) {
|
|
149
|
+
const tokens = [];
|
|
150
|
+
let current = "";
|
|
151
|
+
for (const char of label.toLowerCase()) {
|
|
152
|
+
const code = char.charCodeAt(0);
|
|
153
|
+
const isAsciiLetter = code >= 97 && code <= 122;
|
|
154
|
+
const isAsciiDigit = code >= 48 && code <= 57;
|
|
155
|
+
if (isAsciiLetter || isAsciiDigit) {
|
|
156
|
+
current += char;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (current.length > 0) {
|
|
160
|
+
tokens.push(current);
|
|
161
|
+
current = "";
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (current.length > 0) {
|
|
165
|
+
tokens.push(current);
|
|
166
|
+
}
|
|
167
|
+
return tokens;
|
|
129
168
|
}
|
|
130
169
|
function isValidUrl(value) {
|
|
131
170
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-client.js","sourceRoot":"","sources":["../../src/services/llm-client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AA0B3D,MAAM,UAAU,eAAe,CAAC,OAAyB;IACvD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,uBAAuB,EAAE,CAAC;IAEnE,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,OAAO;YAChB,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,UAAU,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAC3F,OAAO,EAAE,OAAO,EAAE,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/C,CAAC;QAED,KAAK,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"llm-client.js","sourceRoot":"","sources":["../../src/services/llm-client.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -55,7 +55,8 @@ async function loadPackage(fs, rootDir, relDir, isRoot) {
|
|
|
55
55
|
files: Array.isArray(pkg.files)
|
|
56
56
|
? pkg.files.filter((f) => typeof f === "string")
|
|
57
57
|
: [],
|
|
58
|
-
scripts: toStringRecord(pkg.scripts)
|
|
58
|
+
scripts: toStringRecord(pkg.scripts),
|
|
59
|
+
hasReadme: entries.some((e) => e.name === "README.md" && !e.isDirectory())
|
|
59
60
|
};
|
|
60
61
|
}
|
|
61
62
|
function packageDirOf(targetPath) {
|
|
@@ -9,6 +9,7 @@ import { importedWorkspaceDepUnresolvable } from "./imported-workspace-dep-unres
|
|
|
9
9
|
import { exportsSubpathResolvable } from "./exports-subpath-resolvable.js";
|
|
10
10
|
import { bundleSelfContained } from "./bundle-self-contained.js";
|
|
11
11
|
import { publishedBinMustBeExecutable } from "./published-bin-must-be-executable.js";
|
|
12
|
+
import { packageReadmeRequired } from "./package-readme-required.js";
|
|
12
13
|
export const rules = [
|
|
13
14
|
shippedDistDepsUnresolvable,
|
|
14
15
|
noPublishedToPrivateDep,
|
|
@@ -20,7 +21,8 @@ export const rules = [
|
|
|
20
21
|
importedWorkspaceDepUnresolvable,
|
|
21
22
|
exportsSubpathResolvable,
|
|
22
23
|
bundleSelfContained,
|
|
23
|
-
publishedBinMustBeExecutable
|
|
24
|
+
publishedBinMustBeExecutable,
|
|
25
|
+
packageReadmeRequired
|
|
24
26
|
];
|
|
25
27
|
export function runRules(model, build, only) {
|
|
26
28
|
if (only && only.length > 0) {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const id = "package-readme-required";
|
|
2
|
+
export const packageReadmeRequired = {
|
|
3
|
+
id,
|
|
4
|
+
run(model) {
|
|
5
|
+
const violations = [];
|
|
6
|
+
for (const pkg of model.packages) {
|
|
7
|
+
if (pkg.hasReadme)
|
|
8
|
+
continue;
|
|
9
|
+
const readmePath = `${pkg.dir}/README.md`;
|
|
10
|
+
violations.push({
|
|
11
|
+
rule: id,
|
|
12
|
+
package: pkg.name,
|
|
13
|
+
severity: "error",
|
|
14
|
+
detail: { path: readmePath },
|
|
15
|
+
message: `workspace package is missing ${readmePath}`,
|
|
16
|
+
fix: `Add ${readmePath} documenting exposed environment variables and config options.`
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
return violations;
|
|
20
|
+
}
|
|
21
|
+
};
|