Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

fastapi-poe

Package Overview
Dependencies
Maintainers
0
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fastapi-poe - npm Package Compare versions

Comparing version 0.2.0 to 0.2.1

dist/bin.js.map

113

dist/bin.js

@@ -1,36 +0,42 @@

import { Command as i } from "commander";
import { confirm as m, password as p } from "@inquirer/prompts";
import t from "node:path";
import { access as d, cp as u, writeFile as n, rename as g, readFile as w } from "node:fs/promises";
import { fileURLToPath as f } from "node:url";
import o from "chalk";
const v = "0.2.0", h = t.resolve(
t.dirname(f(import.meta.url)),
import { Command } from 'commander';
import { confirm, password } from '@inquirer/prompts';
import path from 'node:path';
import { access, cp, writeFile, rename, readFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import chalk from 'chalk';
const version = "0.2.1";
const ROOT_PATH = path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
".."
), y = async (e) => d(e).then(() => !0).catch(() => !1);
async function P(e) {
const r = t.resolve(h, "./packages/poe-bot-template");
await u(r, e.distPath, {
recursive: !0,
force: !0,
dereference: !0,
filter: (a) => t.basename(a) !== "node_modules"
}), await n(
t.resolve(e.distPath, ".dev.vars"),
`ACCESS_KEY="${e.accessKey}"`
);
const pathExists = async (path2) => access(path2).then(() => true).catch(() => false);
async function init(options) {
const srcPath = path.resolve(ROOT_PATH, "./packages/poe-bot-template");
await cp(srcPath, options.distPath, {
recursive: true,
force: true,
dereference: true,
filter: (source) => path.basename(source) !== "node_modules"
});
await writeFile(
path.resolve(options.distPath, ".dev.vars"),
`ACCESS_KEY="${options.accessKey}"`
);
const s = async (a, c) => {
const l = await w(a, "utf-8");
await n(a, c(l));
const replace = async (fsPath, content) => {
const file = await readFile(fsPath, "utf-8");
await writeFile(fsPath, content(file));
};
await Promise.all(
["package.json", "wrangler.toml", "src/index.ts"].map(
(a) => s(
t.resolve(e.distPath, a),
(c) => c.replace("poe-bot-template", e.name)
(it) => replace(
path.resolve(options.distPath, it),
(c) => c.replace("poe-bot-template", options.name)
)
).concat([
g(
t.resolve(e.distPath, "_.gitignore"),
t.resolve(e.distPath, ".gitignore")
rename(
path.resolve(options.distPath, "_.gitignore"),
path.resolve(options.distPath, ".gitignore")
)

@@ -40,24 +46,34 @@ ])

}
new i().addCommand(
new i("init").arguments("<project-name>").action(async (e) => {
const r = t.resolve(e);
if (await y(r) && !await m({
message: "Directory already exists, do you want to overwrite it?",
default: !1
}))
return;
const s = await p({
new Command().addCommand(
new Command("init").arguments("<project-name>").action(async (name) => {
const distPath = path.resolve(name);
if (await pathExists(distPath)) {
const isOverwrite = await confirm({
message: "Directory already exists, do you want to overwrite it?",
default: false
});
if (!isOverwrite) {
return;
}
}
const accessKey = await password({
message: "Input Poe Server Bot Access key",
mask: "*"
});
await P({
name: e,
accessKey: s,
distPath: r
}), console.log(`
✨ PoeAI server bot project create success!
`), console.log("Next steps:"), console.log(` 1. ${o.blue(`cd ${e}`)}`), console.log(` 2. ${o.blue("pnpm i")}`), console.log(` 3. ${o.blue("pnpm dev")}`), console.log(` 4. ${o.blue("pnpm run deploy")}`), console.log(
` 5. ${o.blue(
`echo ${o.bgRed(
s
await init({
name,
accessKey,
distPath
});
console.log("\n✨ PoeAI server bot project create success!\n");
console.log("Next steps:");
console.log(` 1. ${chalk.blue(`cd ${name}`)}`);
console.log(` 2. ${chalk.blue("pnpm i")}`);
console.log(` 3. ${chalk.blue("pnpm dev")}`);
console.log(` 4. ${chalk.blue("pnpm run deploy")}`);
console.log(
` 5. ${chalk.blue(
`echo ${chalk.bgRed(
accessKey
)} | pnpm wrangler secret put ACCESS_KEY`

@@ -67,2 +83,3 @@ )}`

})
).version(v).parse();
).version(version).parse();
//# sourceMappingURL=bin.js.map

@@ -1,66 +0,89 @@

import { streamSSE as f } from "hono/streaming";
const h = "1.0";
class w extends Error {
constructor(r) {
super(r), this.name = "BotError";
import { streamSSE } from 'hono/streaming';
const PROTOCOL_VERSION = "1.0";
class BotError extends Error {
constructor(message) {
super(message);
this.name = "BotError";
}
}
async function p(e, r = "", o = "https://api.poe.com/bot/fetch_settings") {
const t = await fetch(
`${o}/${e}/${r}/${h}`,
async function syncBotSettings(botName, accessKey = "", baseUrl = "https://api.poe.com/bot/fetch_settings") {
const resp = await fetch(
`${baseUrl}/${botName}/${accessKey}/${PROTOCOL_VERSION}`,
{
method: "post"
}
), n = await t.text();
if (!t.ok)
throw new w(`Error fetching settings for bot ${e}: ${n}`);
console.log(n);
);
const text = await resp.text();
if (!resp.ok) {
throw new BotError(`Error fetching settings for bot ${botName}: ${text}`);
}
console.log(text);
}
function S() {
let e = "";
function sseTransformStream() {
let buffer = "";
return new TransformStream({
transform(r, o) {
if (e += r.trim(), e.endsWith('"}') || e.endsWith("{}")) {
const t = e.match(/event:\s*(\w+)/), n = e.match(/data:\s*({.*})/);
if (t && n) {
const s = t[1], a = n[1];
if (s === "text" && a !== "{}")
o.enqueue({
event: s,
data: JSON.parse(a)
transform(chunk, controller) {
buffer += chunk;
const textRegexp = /^event: text[\r\n]+data: ({[\s\S]*?})/;
const doneRegexp = /^event: done[\r\n]+data: ({})/;
while (buffer) {
buffer = buffer.trimStart();
if (textRegexp.test(buffer)) {
const match = buffer.match(textRegexp);
if (match) {
controller.enqueue({
event: "text",
data: JSON.parse(match[1])
});
else if (s === "done") {
o.terminate();
buffer = buffer.replace(match[0], "").trimStart();
}
} else if (doneRegexp.test(buffer)) {
const match = buffer.match(doneRegexp);
if (match) {
buffer = buffer.replace(match[0], "").trimStart();
controller.terminate();
return;
}
} else if (/^ping$/m.test(buffer)) {
const match = buffer.match(/^ping$/m);
if (match) {
buffer = buffer.replace(match[0], "").trimStart();
}
} else if (buffer.trim() === ": ping") {
buffer = buffer.replace(": ping", "").trimStart();
} else {
return;
}
e = "";
}
},
flush() {
e.trim() && console.warn("Unprocessed data in buffer:", e);
if (buffer.trim()) {
console.warn("Unprocessed data in buffer:", buffer);
}
}
});
}
async function* m(e, r, o) {
const n = `https://api.poe.com/bot/${r}`, s = await fetch(n, {
async function* streamRequest(request, botName, accessKey) {
const response = await fetch(`https://api.poe.com/bot/${botName}`, {
method: "post",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${o}`,
Authorization: `Bearer ${accessKey}`,
Accept: "text/event-stream",
"Cache-Control": "no-cache"
},
body: JSON.stringify(e)
body: JSON.stringify(request)
});
if (!s.ok || !s.body)
throw new Error(`HTTP error! status: ${s.status}`);
const a = s.body.pipeThrough(new TextDecoderStream()).pipeThrough(S()).getReader();
let c = await a.read();
for (; !c.done; ) {
const i = c.value;
let d = "";
switch (i.event) {
if (!response.ok || !response.body) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const reader = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(sseTransformStream()).getReader();
let chunk = await reader.read();
while (!chunk.done) {
const parsed = chunk.value;
let text = "";
switch (parsed.event) {
case "text":
d = i.data.text;
text = parsed.data.text;
break;

@@ -70,56 +93,68 @@ case "done":

default:
throw new Error(`Unexpected event: ${i.event}`);
throw new Error(`Unexpected event: ${parsed.event}`);
}
yield { text: d }, c = await a.read();
yield { text };
chunk = await reader.read();
}
}
function y(e) {
let r = "";
const o = async (t) => {
if (r || (r = t.env.ACCESS_KEY), !r)
function poe(options) {
function handleQuery(query, c) {
return streamSSE(c, async (stream) => {
await stream.writeSSE({
event: "meta",
data: JSON.stringify({ content_type: "text/markdown" })
});
const list = options.getResponse(query);
for await (const it of list) {
if (it.is_replace_response) {
stream.writeSSE({
event: "replace_response",
data: JSON.stringify(it)
});
} else {
stream.writeSSE({ event: "text", data: JSON.stringify(it) });
}
}
stream.writeSSE({ event: "done", data: JSON.stringify({}) });
});
}
let key = "";
const handler = async (c) => {
if (!key) {
throw new Error("Access Key is required");
function n(c) {
return f(t, async (i) => {
await i.writeSSE({
event: "meta",
data: JSON.stringify({ content_type: "text/markdown" })
});
const d = e.getResponse(c);
for await (const u of d)
u.is_replace_response ? i.writeSSE({
event: "replace_response",
data: JSON.stringify(u)
}) : i.writeSSE({ event: "text", data: JSON.stringify(u) });
i.writeSSE({ event: "done", data: JSON.stringify({}) });
});
}
if (t.req.header().authorization !== `Bearer ${r}`)
return t.text("Unauthorized", 401);
const a = await t.req.json();
switch (a.type) {
const authHeader = c.req.header().authorization;
if (authHeader !== `Bearer ${key}`) {
return c.text("Unauthorized", 401);
}
const req = await c.req.json();
switch (req.type) {
case "query":
return n(a);
return handleQuery(req, c);
case "settings":
return t.json(await e.getSettings(a));
return c.json(await options.getSettings(req));
case "report_feedback":
return await e.onFeedback?.(a), t.json({});
await options.onFeedback?.(req);
return c.json({});
case "report_error":
return await e.onError?.(a), t.json({});
await options.onError?.(req);
return c.json({});
default:
return t.text("501 Not Implemented", 501);
return c.text("501 Not Implemented", 501);
}
};
if (!e.name)
if (!options.name) {
throw new Error("name and key are required");
}
return {
handler: o,
set accessKey(t) {
r = t;
handler,
set accessKey(value) {
key = value;
},
syncBotSettings: () => p(e.name, r),
streamRequest: (t, n) => m(t, n, r)
syncBotSettings: () => syncBotSettings(options.name, key),
streamRequest: (request, botName) => streamRequest(request, botName, key)
};
}
export {
y as poe
};
export { poe };
//# sourceMappingURL=index.js.map

@@ -35,4 +35,4 @@ import { Handler } from 'hono';

export declare function parseSSEMessage(message: string): ParsedDone | ParsedText;
export declare function streamSSETransformStream(): TransformStream<string, {
event: "text" | "done";
export declare function sseTransformStream(): TransformStream<string, {
event: "text";
data: any;

@@ -39,0 +39,0 @@ }>;

{
"name": "fastapi-poe",
"version": "0.2.0",
"version": "0.2.1",
"type": "module",

@@ -5,0 +5,0 @@ "bin": {

@@ -10,3 +10,3 @@ {

"dependencies": {
"fastapi-poe": "^0.1.0",
"fastapi-poe": "^0.2.1",
"hono": "^4.5.6"

@@ -13,0 +13,0 @@ },

@@ -17,5 +17,2 @@ import { Hono } from 'hono'

},
allow_attachments: false,
suggested_replies: true,
enable_markdown: true,
}

@@ -22,0 +19,0 @@ },

@@ -29,21 +29,21 @@ # fastapi-poe

```ts
import { Hono } from 'hono'
import { poe } from 'fastapi-poe'
const app = new Hono()
interface Env {
ACCESS_KEY: string
}
const bot = poe({
name: 'custom-bot',
// settings, https://creator.poe.com/docs/poe-protocol-specification#settings
name: 'poe-bot-template',
getSettings() {
return {
// declare other bots as dependencies
server_bot_dependencies: {
'Claude-3.5-Sonnet': 1,
},
allow_attachments: false,
suggested_replies: true,
enable_markdown: true,
}
},
// get response from bot, https://creator.poe.com/docs/poe-protocol-specification#query
async *getResponse(req) {
// call other bots
for await (const response of bot.streamRequest(req, 'Claude-3.5-Sonnet')) {

@@ -56,2 +56,12 @@ yield {

})
app.post('/', bot.handler)
app.get('/', async (c) => c.text('Hello Hono!'))
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
bot.accessKey = env.ACCESS_KEY
return app.fetch(request, env, ctx)
},
}
```

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc