@scoopika/scoopika
Advanced tools
Comparing version 1.0.2 to 1.0.3
@@ -252,2 +252,9 @@ import OpenAI from 'openai'; | ||
} | ||
interface BoxStream { | ||
agent_name: string; | ||
prompt_name: string; | ||
run_id: string; | ||
content: string; | ||
} | ||
type BoxStreamFunc = (stream: BoxStream) => (undefined | void | unknown); | ||
@@ -334,2 +341,56 @@ declare class InMemoryStore implements Store { | ||
export { Agent, InMemoryStore }; | ||
declare class Box { | ||
id: string; | ||
client: Scoopika; | ||
box: BoxData | undefined; | ||
llm_clients: LLMClient[]; | ||
tools: ToolSchema[]; | ||
agents_tools: Record<string, ToolSchema[]>; | ||
mentions: boolean; | ||
running_agent: string; | ||
stream_listeners: BoxStreamFunc[]; | ||
prompt_listeners: ((response: LLMResponse) => any)[]; | ||
agent_selection_listeners: ((agent: AgentData) => any)[]; | ||
finish_listeners: ((response: { | ||
name: string; | ||
run: AgentResponse; | ||
}[]) => any)[]; | ||
constructor(id: string, client: Scoopika, { box, engines, system_prompt, tools, mentions, }: { | ||
box?: BoxData; | ||
engines?: RawEngines; | ||
system_prompt?: string; | ||
mentions?: boolean; | ||
tools?: ToolSchema[]; | ||
}); | ||
load(): Promise<Box>; | ||
run(inputs: Inputs): Promise<{ | ||
name: string; | ||
run: AgentResponse; | ||
}[]>; | ||
selectAgents(inputs: Inputs, history: LLMHistory[]): Promise<{ | ||
name: string; | ||
instructions: string; | ||
}[]>; | ||
getClient(): { | ||
model: string; | ||
client: LLMClient; | ||
}; | ||
setupHistory(session: StoreSession, inputs: Inputs, history: LLMHistory[]): LLMHistory[]; | ||
buildTools(): ToolSchema[]; | ||
getStreamFunc(): BoxStreamFunc; | ||
getPromptStreamFunc(): (response: LLMResponse) => any; | ||
onStream(func: BoxStreamFunc): this; | ||
onPromptResponse(func: (response: LLMResponse) => any): void; | ||
onToken(func: (message: StreamMessage) => any): void; | ||
onImage(func: (img: LLMImageResponse) => any): void; | ||
onSelectAgent(func: (agent: AgentData) => any): void; | ||
onFinish(func: (response: { | ||
name: string; | ||
run: AgentResponse; | ||
}[]) => any): void; | ||
addGlobalTool(func: (args: Record<string, any>) => any, tool: ToolFunction): void; | ||
addTool(agent_name: string, func: (args: Record<string, any>) => any, tool: ToolFunction): void; | ||
system_prompt: string; | ||
} | ||
export { Agent, Box, InMemoryStore, Scoopika }; |
@@ -34,3 +34,5 @@ "use strict"; | ||
Agent: () => agent_default, | ||
InMemoryStore: () => store_default | ||
Box: () => box_default, | ||
InMemoryStore: () => store_default, | ||
Scoopika: () => scoopika_default | ||
}); | ||
@@ -1275,7 +1277,406 @@ module.exports = __toCommonJS(src_exports); | ||
var store_default = InMemoryStore; | ||
// src/scoopika.ts | ||
var import_node_crypto4 = __toESM(require("crypto")); | ||
var Scoopika = class { | ||
url = "https://scoopika-source.deno.dev"; | ||
// Main API Url to get source data | ||
token; | ||
store; | ||
memoryStore; | ||
engines = {}; | ||
loadedSessions = {}; | ||
stateStore; | ||
constructor({ | ||
token, | ||
store, | ||
engines | ||
}) { | ||
this.token = token; | ||
this.stateStore = new state_default(); | ||
this.memoryStore = new store_default(); | ||
this.engines = engines; | ||
if (store === "memory") { | ||
this.store = new store_default(); | ||
} | ||
this.store = new store_default(); | ||
} | ||
async getSession(id, allow_new) { | ||
const loaded = this.loadedSessions[id]; | ||
if (loaded) { | ||
return loaded; | ||
} | ||
let session = await this.store.getSession(id); | ||
if (!session && allow_new === false) { | ||
throw new Error(`Session '${id}' not found`); | ||
} | ||
if (!session) { | ||
session = await this.newSession({ id }); | ||
} | ||
this.loadedSessions[id] = session; | ||
return session; | ||
} | ||
async newSession({ | ||
id, | ||
user_name | ||
}) { | ||
const session_id = id || "session_" + import_node_crypto4.default.randomUUID(); | ||
await this.store.newSession(session_id, user_name); | ||
this.loadedSessions[session_id] = { | ||
id: session_id, | ||
user_name, | ||
saved_prompts: {} | ||
}; | ||
this.stateStore.setState(session_id, 0); | ||
return { id, user_name, saved_prompts: {} }; | ||
} | ||
async loadAgent(id) { | ||
const res = await fetch(this.url + `/agent/${id}`, { | ||
method: "GET", | ||
headers: { | ||
authorization: this.token | ||
} | ||
}); | ||
const status = res.status; | ||
const data = await res.json(); | ||
if (status !== 200) { | ||
throw new Error(data.error || `Server error, status: ${status}`); | ||
} | ||
if (!data.agent || typeof data.agent !== "object") { | ||
throw new Error("Invalid server response"); | ||
} | ||
return data.agent; | ||
} | ||
async loadBox(id) { | ||
const res = await fetch(this.url + `/box/${id}`, { | ||
method: "GET", | ||
headers: { | ||
authorization: this.token | ||
} | ||
}); | ||
const status = res.status; | ||
const data = await res.json(); | ||
if (status !== 200) { | ||
throw new Error(data.error || `Server error, status: ${status}`); | ||
} | ||
if (!data.box || typeof data.box !== "object") { | ||
throw new Error("Invalid server response"); | ||
} | ||
return data.box; | ||
} | ||
}; | ||
var scoopika_default = Scoopika; | ||
// src/box.ts | ||
var import_node_crypto5 = __toESM(require("crypto")); | ||
var Box = class { | ||
id; | ||
client; | ||
box = void 0; | ||
llm_clients = []; | ||
tools = []; | ||
agents_tools = {}; | ||
mentions = true; | ||
running_agent = "NONE"; | ||
stream_listeners = []; | ||
prompt_listeners = []; | ||
agent_selection_listeners = []; | ||
finish_listeners = []; | ||
constructor(id, client, { | ||
box, | ||
engines, | ||
system_prompt, | ||
tools, | ||
mentions | ||
}) { | ||
this.id = id; | ||
this.client = client; | ||
this.box = box; | ||
if (engines) { | ||
this.llm_clients = buildClients(engines); | ||
} else if (client.engines) { | ||
this.llm_clients = buildClients(client.engines); | ||
} | ||
if (system_prompt) { | ||
this.system_prompt = system_prompt; | ||
} | ||
if (tools) { | ||
this.tools = tools; | ||
} | ||
if (typeof mentions === "boolean") { | ||
this.mentions = mentions; | ||
} | ||
} | ||
async load() { | ||
if (this.box) { | ||
return this; | ||
} | ||
this.box = await this.client.loadBox(this.id); | ||
return this; | ||
} | ||
async run(inputs) { | ||
if (!this.box) { | ||
await this.load(); | ||
} | ||
const session_id = typeof inputs.session_id === "string" ? inputs.session_id : "session_" + import_node_crypto5.default.randomUUID(); | ||
const box = this.box; | ||
const session = await this.client.getSession(session_id); | ||
const run_id = "run_" + import_node_crypto5.default.randomUUID(); | ||
const streamFunc = this.getStreamFunc(); | ||
const promptStreamFunc = this.getPromptStreamFunc(); | ||
if (typeof inputs.run_id !== "string") { | ||
inputs.run_id = run_id; | ||
} | ||
const history = this.setupHistory( | ||
session, | ||
inputs, | ||
await this.client.store.getHistory(session) | ||
); | ||
const selected_agents = await this.selectAgents(inputs, history); | ||
const responses = []; | ||
for (const selected of selected_agents) { | ||
const agentData = box == null ? void 0 : box.agents.filter( | ||
(a) => a.name.toLowerCase() === selected.name.toLowerCase() | ||
)[0]; | ||
if (!agentData) { | ||
continue; | ||
} | ||
this.agent_selection_listeners.forEach((listener) => listener(agentData)); | ||
const agent = new agent_default(agentData.id, this.client, { | ||
agent: { | ||
...agentData, | ||
tools: [ | ||
...agentData.tools, | ||
...this.tools, | ||
...this.agents_tools[agentData.name.toLowerCase()] || [] | ||
] | ||
} | ||
}); | ||
agent.onStream((stream) => { | ||
streamFunc({ | ||
prompt_name: stream.prompt_name, | ||
run_id: stream.run_id, | ||
content: stream.content, | ||
agent_name: this.running_agent | ||
}); | ||
}); | ||
agent.onPromptResponse((response) => { | ||
promptStreamFunc(response); | ||
}); | ||
this.running_agent = agentData.name; | ||
const run = await agent.run({ | ||
...inputs, | ||
message: selected.instructions | ||
}); | ||
responses.push({ name: agentData.name, run }); | ||
} | ||
this.finish_listeners.forEach((listener) => listener(responses)); | ||
return responses; | ||
} | ||
async selectAgents(inputs, history) { | ||
var _a; | ||
if (!inputs.message) { | ||
throw new Error("Inputs message is required in AI Boxes"); | ||
} | ||
if (this.mentions && inputs.message.startsWith("@")) { | ||
const wanted_agents = (_a = this.box) == null ? void 0 : _a.agents.filter( | ||
(agent) => { | ||
var _a2; | ||
return agent.name.toLowerCase() === ((_a2 = inputs.message) == null ? void 0 : _a2.split(" ")[0].replace("@", "").toLowerCase()); | ||
} | ||
); | ||
if (wanted_agents && (wanted_agents == null ? void 0 : wanted_agents.length) > 0) { | ||
return [{ name: wanted_agents[0].name, instructions: inputs.message }]; | ||
} | ||
} | ||
const messages = [ | ||
{ | ||
role: "system", | ||
content: this.system_prompt | ||
}, | ||
...history | ||
]; | ||
if (history.length > 2) { | ||
messages.push({ | ||
role: "user", | ||
content: this.system_prompt | ||
}); | ||
} | ||
if (inputs.message) { | ||
messages.push({ | ||
role: "user", | ||
content: `Instructions: | ||
${inputs.message}` | ||
}); | ||
} | ||
const { model, client } = this.getClient(); | ||
const tools = this.buildTools(); | ||
const modelRunner = new model_default(client, void 0, tools); | ||
const LLM_inputs = { | ||
tools: tools.map((tool) => tool.tool), | ||
tool_choice: "any", | ||
messages, | ||
model, | ||
options: { | ||
temperature: 0 | ||
} | ||
}; | ||
const run = await modelRunner.baseRun( | ||
"BOX", | ||
() => { | ||
}, | ||
() => { | ||
}, | ||
LLM_inputs, | ||
false, | ||
void 0, | ||
false | ||
); | ||
if (!run.tool_calls || run.tool_calls.length < 1) { | ||
return []; | ||
} | ||
if (run.tool_calls.length === 1) { | ||
return [ | ||
{ | ||
name: run.tool_calls[0].function.name, | ||
instructions: inputs.message | ||
} | ||
]; | ||
} | ||
const selected_agents = []; | ||
for (const call of run.tool_calls) { | ||
const args = JSON.parse(call.function.arguments); | ||
if (!args.instructions || typeof args.instructions !== "boolean") { | ||
args.instructions = inputs.message; | ||
} | ||
selected_agents.push({ | ||
name: call.function.name, | ||
instructions: args.instructions | ||
}); | ||
} | ||
return selected_agents; | ||
} | ||
getClient() { | ||
const box = this.box; | ||
const wanted_clients = this.llm_clients.filter( | ||
(l) => l.host === box.llm_client | ||
); | ||
if ((wanted_clients == null ? void 0 : wanted_clients.length) < 1) { | ||
throw new Error(`LLM Client not found for ${box.llm_client}`); | ||
} | ||
return { model: box.manager, client: wanted_clients[0] }; | ||
} | ||
setupHistory(session, inputs, history) { | ||
const newHistory = JSON.parse(JSON.stringify(history)); | ||
if (typeof inputs.message === "string") { | ||
newHistory.push({ | ||
role: "user", | ||
name: session.user_name || "User", | ||
content: inputs.message | ||
}); | ||
} | ||
return newHistory; | ||
} | ||
buildTools() { | ||
if (!this.box) { | ||
return []; | ||
} | ||
const tools = []; | ||
for (const agent of this.box.agents) { | ||
tools.push({ | ||
type: "function", | ||
executor: () => { | ||
}, | ||
tool: { | ||
type: "function", | ||
function: { | ||
name: agent.name, | ||
description: `${agent.name} is an agent. task: ${agent.description}`, | ||
parameters: { | ||
type: "object", | ||
properties: { | ||
instructions: { | ||
type: "string", | ||
description: "The instruction or task to give the agent" | ||
} | ||
}, | ||
required: ["instructions"] | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
return tools; | ||
} | ||
getStreamFunc() { | ||
const listeners = this.stream_listeners; | ||
return (message) => { | ||
listeners.map((listener) => listener(message)); | ||
}; | ||
} | ||
getPromptStreamFunc() { | ||
const listeners = this.prompt_listeners; | ||
return (response) => { | ||
listeners.map((listener) => { | ||
listener(response); | ||
}); | ||
}; | ||
} | ||
onStream(func) { | ||
this.stream_listeners.push(func); | ||
return this; | ||
} | ||
onPromptResponse(func) { | ||
this.prompt_listeners.push(func); | ||
} | ||
onToken(func) { | ||
this.stream_listeners.push(func); | ||
} | ||
onImage(func) { | ||
this.prompt_listeners.push((response) => { | ||
if (response.type !== "image") { | ||
return; | ||
} | ||
func(response); | ||
}); | ||
} | ||
onSelectAgent(func) { | ||
this.agent_selection_listeners.push(func); | ||
} | ||
onFinish(func) { | ||
this.finish_listeners.push(func); | ||
} | ||
addGlobalTool(func, tool) { | ||
this.tools.push({ | ||
type: "function", | ||
executor: func, | ||
tool: { | ||
type: "function", | ||
function: tool | ||
} | ||
}); | ||
} | ||
addTool(agent_name, func, tool) { | ||
if (!this.agents_tools[agent_name.toLowerCase()]) { | ||
this.agents_tools[agent_name.toLowerCase()] = []; | ||
} | ||
this.agents_tools[agent_name.toLowerCase()].push({ | ||
type: "function", | ||
executor: func, | ||
tool: { | ||
type: "function", | ||
function: tool | ||
} | ||
}); | ||
} | ||
system_prompt = `You are a manager that chooses from a number of AI agents to execute a specific task. choose the most suitable agent for the task.`; | ||
}; | ||
var box_default = Box; | ||
// Annotate the CommonJS export names for ESM import in node: | ||
0 && (module.exports = { | ||
Agent, | ||
InMemoryStore | ||
Box, | ||
InMemoryStore, | ||
Scoopika | ||
}); | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "@scoopika/scoopika", | ||
"version": "1.0.2", | ||
"version": "1.0.3", | ||
"description": "Create magical AI agents and boxes with multiple agents in seconds", | ||
@@ -5,0 +5,0 @@ "main": "dist/src/main.js", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
358787
5968
6