agentlaunch-templates 0.4.2 → 0.4.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.
|
@@ -1,19 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* chat-memory.ts — Base template with
|
|
2
|
+
* chat-memory.ts — Base template with chat memory and context
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
8
|
-
* - Clean Chat Protocol v0.3.0 implementation
|
|
9
|
-
* - Session persistence via ctx.storage
|
|
10
|
-
* - Lazy LLM client initialization (avoids compile-time issues)
|
|
11
|
-
*
|
|
12
|
-
* Compatible LLM providers:
|
|
13
|
-
* - ASI1: https://api.asi1.ai/v1 (default)
|
|
14
|
-
* - OpenRouter: https://openrouter.ai/api/v1
|
|
15
|
-
* - OpenAI: https://api.openai.com/v1
|
|
16
|
-
* - Any OpenAI-compatible endpoint
|
|
4
|
+
* Platform constants (source of truth: deployed smart contracts):
|
|
5
|
+
* - Deploy fee: 120 FET (read dynamically, can change via multi-sig)
|
|
6
|
+
* - Graduation target: 30,000 FET -> auto DEX listing
|
|
7
|
+
* - Trading fee: 2% -> 100% to protocol treasury (NO creator fee)
|
|
17
8
|
*/
|
|
18
9
|
import type { AgentTemplate } from "../registry.js";
|
|
19
10
|
export declare const template: AgentTemplate;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-memory.d.ts","sourceRoot":"","sources":["../../src/templates/chat-memory.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"chat-memory.d.ts","sourceRoot":"","sources":["../../src/templates/chat-memory.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAQpD,eAAO,MAAM,QAAQ,EAAE,aA+LtB,CAAC"}
|
|
@@ -1,279 +1,201 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* chat-memory.ts — Base template with
|
|
2
|
+
* chat-memory.ts — Base template with chat memory and context
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
8
|
-
* - Clean Chat Protocol v0.3.0 implementation
|
|
9
|
-
* - Session persistence via ctx.storage
|
|
10
|
-
* - Lazy LLM client initialization (avoids compile-time issues)
|
|
11
|
-
*
|
|
12
|
-
* Compatible LLM providers:
|
|
13
|
-
* - ASI1: https://api.asi1.ai/v1 (default)
|
|
14
|
-
* - OpenRouter: https://openrouter.ai/api/v1
|
|
15
|
-
* - OpenAI: https://api.openai.com/v1
|
|
16
|
-
* - Any OpenAI-compatible endpoint
|
|
4
|
+
* Platform constants (source of truth: deployed smart contracts):
|
|
5
|
+
* - Deploy fee: 120 FET (read dynamically, can change via multi-sig)
|
|
6
|
+
* - Graduation target: 30,000 FET -> auto DEX listing
|
|
7
|
+
* - Trading fee: 2% -> 100% to protocol treasury (NO creator fee)
|
|
17
8
|
*/
|
|
9
|
+
// Environment-based URL resolution (production is default, set AGENT_LAUNCH_ENV=dev for dev)
|
|
10
|
+
const PROD_API_URL = 'https://agent-launch.ai/api';
|
|
11
|
+
const DEV_API_URL = 'https://launchpad-backend-dev-1056182620041.us-central1.run.app';
|
|
12
|
+
const RESOLVED_API_URL = process.env.AGENT_LAUNCH_API_URL ??
|
|
13
|
+
(process.env.AGENT_LAUNCH_ENV === 'dev' ? DEV_API_URL : PROD_API_URL);
|
|
18
14
|
export const template = {
|
|
19
15
|
name: "chat-memory",
|
|
20
|
-
description: "
|
|
21
|
-
category: "
|
|
16
|
+
description: "Chat agent with conversation memory — recommended starting point",
|
|
17
|
+
category: "General",
|
|
22
18
|
variables: [
|
|
23
19
|
{ name: "agent_name", required: true, description: "Name of the agent" },
|
|
24
20
|
{
|
|
25
21
|
name: "description",
|
|
26
|
-
required:
|
|
27
|
-
default: "AI assistant with conversation memory",
|
|
22
|
+
required: true,
|
|
28
23
|
description: "Short description of what this agent does",
|
|
29
24
|
},
|
|
30
25
|
{
|
|
31
|
-
name: "
|
|
32
|
-
default: "You are a helpful AI assistant. Be concise and accurate.",
|
|
33
|
-
description: "System prompt that defines the agent's personality and knowledge",
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
name: "llm_base_url",
|
|
37
|
-
default: "https://api.asi1.ai/v1",
|
|
38
|
-
description: "LLM API base URL (ASI1, OpenRouter, OpenAI, or compatible)",
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
name: "llm_model",
|
|
42
|
-
default: "asi1-mini",
|
|
43
|
-
description: "Model name to use (e.g., asi1-mini, gpt-4o-mini, claude-3-haiku)",
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
name: "max_history",
|
|
26
|
+
name: "memory_size",
|
|
47
27
|
default: "10",
|
|
48
|
-
description: "Number of
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
name: "max_tokens",
|
|
52
|
-
default: "1500",
|
|
53
|
-
description: "Maximum tokens in LLM response",
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
name: "temperature",
|
|
57
|
-
default: "0.7",
|
|
58
|
-
description: "LLM temperature (0.0-1.0, lower = more deterministic)",
|
|
28
|
+
description: "Number of messages to remember per user",
|
|
59
29
|
},
|
|
60
30
|
],
|
|
61
|
-
dependencies: ["
|
|
62
|
-
secrets: ["
|
|
63
|
-
code:
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
{{
|
|
67
|
-
|
|
68
|
-
Built with the chat-memory template.
|
|
69
|
-
Supports ASI1, OpenRouter, OpenAI, or any OpenAI-compatible LLM.
|
|
31
|
+
dependencies: ["requests"],
|
|
32
|
+
secrets: ["AGENTVERSE_API_KEY", "AGENTLAUNCH_API_KEY", "AGENT_ADDRESS"],
|
|
33
|
+
code: `#!/usr/bin/env python3
|
|
34
|
+
"""
|
|
35
|
+
{{agent_name}} — AgentLaunch Chat Memory Agent
|
|
36
|
+
Generated by: agentlaunch scaffold {{agent_name}} --type chat-memory
|
|
70
37
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
SYSTEM_PROMPT - Override the default system prompt
|
|
38
|
+
Platform constants (source of truth: deployed smart contracts):
|
|
39
|
+
- Deploy fee: 120 FET (read dynamically, can change via multi-sig)
|
|
40
|
+
- Graduation target: 30,000 FET -> auto DEX listing
|
|
41
|
+
- Trading fee: 2% -> 100% to protocol treasury (NO creator fee)
|
|
76
42
|
"""
|
|
77
43
|
|
|
78
44
|
from uagents import Agent, Context, Protocol
|
|
79
45
|
from uagents_core.contrib.protocols.chat import (
|
|
80
|
-
|
|
81
|
-
|
|
46
|
+
ChatAcknowledgement,
|
|
47
|
+
ChatMessage,
|
|
48
|
+
EndSessionContent,
|
|
49
|
+
TextContent,
|
|
50
|
+
chat_protocol_spec,
|
|
82
51
|
)
|
|
83
|
-
|
|
52
|
+
|
|
84
53
|
import json
|
|
85
54
|
import os
|
|
55
|
+
from collections import defaultdict
|
|
56
|
+
from datetime import datetime
|
|
57
|
+
from typing import Dict, List
|
|
58
|
+
from uuid import uuid4
|
|
86
59
|
|
|
87
|
-
|
|
88
|
-
|
|
60
|
+
# ==============================================================================
|
|
61
|
+
# CONFIG
|
|
62
|
+
# ==============================================================================
|
|
89
63
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
# =============================================================================
|
|
64
|
+
AGENTLAUNCH_API = os.environ.get("AGENTLAUNCH_API", "${RESOLVED_API_URL}")
|
|
65
|
+
MEMORY_SIZE = {{memory_size}}
|
|
93
66
|
|
|
94
|
-
|
|
67
|
+
BUSINESS = {
|
|
95
68
|
"name": "{{agent_name}}",
|
|
96
69
|
"description": "{{description}}",
|
|
97
|
-
"
|
|
98
|
-
"llm_model": os.environ.get("LLM_MODEL", "{{llm_model}}"),
|
|
99
|
-
"max_history": {{max_history}},
|
|
100
|
-
"max_tokens": {{max_tokens}},
|
|
101
|
-
"temperature": {{temperature}},
|
|
70
|
+
"version": "1.0.0",
|
|
102
71
|
}
|
|
103
72
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
SYSTEM_PROMPT = os.environ.get("SYSTEM_PROMPT", DEFAULT_SYSTEM_PROMPT)
|
|
107
|
-
|
|
108
|
-
# =============================================================================
|
|
109
|
-
# LLM CLIENT (Lazy initialization)
|
|
110
|
-
# =============================================================================
|
|
111
|
-
|
|
112
|
-
_llm_client = None
|
|
113
|
-
|
|
114
|
-
def get_llm_client():
|
|
115
|
-
"""Get or create LLM client. Lazy init avoids compile-time issues."""
|
|
116
|
-
global _llm_client
|
|
117
|
-
if _llm_client is None:
|
|
118
|
-
from openai import OpenAI
|
|
119
|
-
_llm_client = OpenAI(
|
|
120
|
-
api_key=os.environ.get("LLM_API_KEY", ""),
|
|
121
|
-
base_url=CONFIG["llm_base_url"]
|
|
122
|
-
)
|
|
123
|
-
return _llm_client
|
|
124
|
-
|
|
125
|
-
# =============================================================================
|
|
73
|
+
# ==============================================================================
|
|
126
74
|
# CONVERSATION MEMORY
|
|
127
|
-
#
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
"""
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
75
|
+
# ==============================================================================
|
|
76
|
+
|
|
77
|
+
class ConversationMemory:
|
|
78
|
+
"""Store recent messages per user for context."""
|
|
79
|
+
|
|
80
|
+
def __init__(self, max_messages: int = MEMORY_SIZE) -> None:
|
|
81
|
+
self._history: Dict[str, List[Dict]] = defaultdict(list)
|
|
82
|
+
self._max = max_messages
|
|
83
|
+
|
|
84
|
+
def add(self, user_id: str, role: str, content: str) -> None:
|
|
85
|
+
self._history[user_id].append({
|
|
86
|
+
"role": role,
|
|
87
|
+
"content": content,
|
|
88
|
+
"timestamp": datetime.utcnow().isoformat(),
|
|
89
|
+
})
|
|
90
|
+
if len(self._history[user_id]) > self._max:
|
|
91
|
+
self._history[user_id] = self._history[user_id][-self._max:]
|
|
92
|
+
|
|
93
|
+
def get(self, user_id: str) -> List[Dict]:
|
|
94
|
+
return list(self._history[user_id])
|
|
95
|
+
|
|
96
|
+
def clear(self, user_id: str) -> None:
|
|
97
|
+
self._history[user_id] = []
|
|
98
|
+
|
|
99
|
+
def summary(self, user_id: str) -> str:
|
|
100
|
+
history = self.get(user_id)
|
|
101
|
+
if not history:
|
|
102
|
+
return "No conversation history."
|
|
103
|
+
lines = [f"- {m['role']}: {m['content'][:100]}" for m in history[-5:]]
|
|
104
|
+
return "\\n".join(lines)
|
|
105
|
+
|
|
106
|
+
# ==============================================================================
|
|
107
|
+
# REPLY HELPER
|
|
108
|
+
# ==============================================================================
|
|
109
|
+
|
|
110
|
+
async def reply(ctx: Context, sender: str, text: str, end: bool = False) -> None:
|
|
111
|
+
content = [TextContent(type="text", text=text)]
|
|
112
|
+
if end:
|
|
113
|
+
content.append(EndSessionContent(type="end-session"))
|
|
167
114
|
try:
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
messages=messages,
|
|
172
|
-
max_tokens=CONFIG["max_tokens"],
|
|
173
|
-
temperature=CONFIG["temperature"]
|
|
115
|
+
await ctx.send(
|
|
116
|
+
sender,
|
|
117
|
+
ChatMessage(timestamp=datetime.utcnow(), msg_id=uuid4(), content=content),
|
|
174
118
|
)
|
|
175
|
-
return response.choices[0].message.content
|
|
176
|
-
|
|
177
119
|
except Exception as e:
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
# =============================================================================
|
|
181
|
-
# RESPONSE HELPERS
|
|
182
|
-
# =============================================================================
|
|
183
|
-
|
|
184
|
-
async def send_text(ctx: Context, sender: str, msg_id: str, text: str, end: bool = False):
|
|
185
|
-
"""Send a text response, optionally ending the session."""
|
|
186
|
-
await ctx.send(sender, ChatMessage(
|
|
187
|
-
timestamp=datetime.now(),
|
|
188
|
-
msg_id=msg_id,
|
|
189
|
-
content=[TextContent(text=text)]
|
|
190
|
-
))
|
|
191
|
-
if end:
|
|
192
|
-
await ctx.send(sender, ChatMessage(
|
|
193
|
-
timestamp=datetime.now(),
|
|
194
|
-
msg_id=msg_id,
|
|
195
|
-
content=[EndSessionContent()]
|
|
196
|
-
))
|
|
197
|
-
|
|
198
|
-
def get_help() -> str:
|
|
199
|
-
"""Return help message."""
|
|
200
|
-
return f"""# {CONFIG["name"]}
|
|
201
|
-
|
|
202
|
-
{CONFIG["description"]}
|
|
120
|
+
ctx.logger.error(f"Failed to send reply: {e}")
|
|
203
121
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
- \`status\` — Show session info
|
|
208
|
-
|
|
209
|
-
Just send a message to start chatting!
|
|
210
|
-
"""
|
|
122
|
+
# ==============================================================================
|
|
123
|
+
# MAIN AGENT
|
|
124
|
+
# ==============================================================================
|
|
211
125
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
126
|
+
memory = ConversationMemory(max_messages=MEMORY_SIZE)
|
|
127
|
+
agent = Agent()
|
|
128
|
+
chat_proto = Protocol(spec=chat_protocol_spec)
|
|
215
129
|
|
|
216
130
|
@chat_proto.on_message(ChatMessage)
|
|
217
|
-
async def
|
|
218
|
-
|
|
219
|
-
|
|
131
|
+
async def handle_chat(ctx: Context, sender: str, msg: ChatMessage) -> None:
|
|
132
|
+
# Send acknowledgement
|
|
133
|
+
try:
|
|
134
|
+
await ctx.send(
|
|
135
|
+
sender,
|
|
136
|
+
ChatAcknowledgement(
|
|
137
|
+
timestamp=datetime.utcnow(), acknowledged_msg_id=msg.msg_id
|
|
138
|
+
),
|
|
139
|
+
)
|
|
140
|
+
except Exception as e:
|
|
141
|
+
ctx.logger.error(f"Failed to send ack: {e}")
|
|
220
142
|
|
|
221
143
|
# Extract text from message
|
|
222
|
-
text = ""
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
text = content.text.strip()
|
|
226
|
-
break
|
|
144
|
+
text = " ".join(
|
|
145
|
+
item.text for item in msg.content if isinstance(item, TextContent)
|
|
146
|
+
).strip()[:2000]
|
|
227
147
|
|
|
228
148
|
if not text:
|
|
229
|
-
await
|
|
149
|
+
await reply(ctx, sender, "Please send a message.", end=True)
|
|
230
150
|
return
|
|
231
151
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
# Get session with conversation history
|
|
235
|
-
session = get_session(ctx, sender)
|
|
152
|
+
lower = text.lower()
|
|
236
153
|
|
|
237
|
-
#
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
154
|
+
# Help command
|
|
155
|
+
if lower in ("help", "?"):
|
|
156
|
+
await reply(
|
|
157
|
+
ctx,
|
|
158
|
+
sender,
|
|
159
|
+
f"**{BUSINESS['name']}** v{BUSINESS['version']}\\n\\n"
|
|
160
|
+
f"{BUSINESS['description']}\\n\\n"
|
|
161
|
+
f"Commands: help, history, clear",
|
|
162
|
+
)
|
|
242
163
|
return
|
|
243
164
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
await
|
|
165
|
+
# History command
|
|
166
|
+
if lower == "history":
|
|
167
|
+
summary = memory.summary(sender)
|
|
168
|
+
await reply(ctx, sender, f"**Recent conversation:**\\n{summary}")
|
|
248
169
|
return
|
|
249
170
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
- Model: {CONFIG['llm_model']}
|
|
255
|
-
- Provider: {CONFIG['llm_base_url']}
|
|
256
|
-
"""
|
|
257
|
-
await send_text(ctx, sender, msg.msg_id, status, end=True)
|
|
171
|
+
# Clear command
|
|
172
|
+
if lower == "clear":
|
|
173
|
+
memory.clear(sender)
|
|
174
|
+
await reply(ctx, sender, "Conversation history cleared.", end=True)
|
|
258
175
|
return
|
|
259
176
|
|
|
260
|
-
#
|
|
261
|
-
|
|
177
|
+
# Store user message
|
|
178
|
+
memory.add(sender, "user", text)
|
|
262
179
|
|
|
263
|
-
#
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
session["message_count"] = session.get("message_count", 0) + 1
|
|
267
|
-
save_session(ctx, sender, session)
|
|
180
|
+
# Get context for response
|
|
181
|
+
history = memory.get(sender)
|
|
182
|
+
context_msgs = len(history) - 1 # Exclude current message
|
|
268
183
|
|
|
269
|
-
|
|
184
|
+
# Generate response (customize this!)
|
|
185
|
+
response = (
|
|
186
|
+
f"I received your message: '{text[:100]}'\\n\\n"
|
|
187
|
+
f"I have {context_msgs} previous messages in memory.\\n\\n"
|
|
188
|
+
f"This is a template — customize the response logic in handle_chat()."
|
|
189
|
+
)
|
|
270
190
|
|
|
191
|
+
# Store assistant response
|
|
192
|
+
memory.add(sender, "assistant", response[:200])
|
|
271
193
|
|
|
272
|
-
|
|
273
|
-
async def handle_ack(ctx: Context, sender: str, msg: ChatAcknowledgement):
|
|
274
|
-
"""Handle acknowledgements (required by protocol)."""
|
|
275
|
-
ctx.logger.info(f"Ack from {sender}: {msg.acknowledged_msg_id}")
|
|
194
|
+
await reply(ctx, sender, response, end=True)
|
|
276
195
|
|
|
196
|
+
@chat_proto.on_message(ChatAcknowledgement)
|
|
197
|
+
async def handle_ack(ctx: Context, sender: str, msg: ChatAcknowledgement) -> None:
|
|
198
|
+
ctx.logger.debug(f"Ack from {sender[:20]} for msg {msg.acknowledged_msg_id}")
|
|
277
199
|
|
|
278
200
|
agent.include(chat_proto, publish_manifest=True)
|
|
279
201
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-memory.js","sourceRoot":"","sources":["../../src/templates/chat-memory.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"chat-memory.js","sourceRoot":"","sources":["../../src/templates/chat-memory.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,6FAA6F;AAC7F,MAAM,YAAY,GAAG,6BAA6B,CAAC;AACnD,MAAM,WAAW,GAAG,iEAAiE,CAAC;AACtF,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB;IACvD,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;AAExE,MAAM,CAAC,MAAM,QAAQ,GAAkB;IACrC,IAAI,EAAE,aAAa;IACnB,WAAW,EAAE,kEAAkE;IAC/E,QAAQ,EAAE,SAAS;IACnB,SAAS,EAAE;QACT,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,mBAAmB,EAAE;QACxE;YACE,IAAI,EAAE,aAAa;YACnB,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,2CAA2C;SACzD;QACD;YACE,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,IAAI;YACb,WAAW,EAAE,yCAAyC;SACvD;KACF;IACD,YAAY,EAAE,CAAC,UAAU,CAAC;IAC1B,OAAO,EAAE,CAAC,oBAAoB,EAAE,qBAAqB,EAAE,eAAe,CAAC;IACvE,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uDA+B+C,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4ItE;CACA,CAAC"}
|