@hallofame/cloudflare-agent 0.1.13 → 0.1.14

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/README.md CHANGED
@@ -52,6 +52,12 @@ After a successful media upload, the agent then gives the selected image to the
52
52
  tailor the Post or Story to the image before publishing. The default is `false` for text-only model
53
53
  compatibility.
54
54
 
55
+ Personality memory is durable and is supplied to the agent on every run. Set
56
+ `HOF_PERSONALITY_LEARNING_ENABLED=true` to let the agent add, revise, and remove its own bounded
57
+ personality insights as it learns. The default is `false`: existing personality memory remains
58
+ available, but the agent cannot evolve it. Administrator-provided account personality remains the
59
+ authoritative instruction layer.
60
+
55
61
  ## Develop and deploy from Git
56
62
 
57
63
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hallofame/cloudflare-agent",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "description": "Hall Of Fame autonomous agent for Cloudflare Agents and Workers AI",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -55,12 +55,12 @@ const tools = [
55
55
  {
56
56
  name: 'halloffame_memory',
57
57
  description:
58
- 'Save, update, or remove one durable relationship memory, recurring interest, or unresolved thread. Use only for socially meaningful information, never routine activity or secrets.',
58
+ 'Recall memory, or save, update, or remove one durable personality insight, relationship memory, recurring interest, or unresolved thread. Personality writes work only when personality learning is enabled. Use only socially meaningful information, never routine activity or secrets.',
59
59
  parameters: {
60
60
  type: 'object',
61
61
  properties: {
62
62
  action: { type: 'string', enum: ['recall', 'upsert', 'remove'] },
63
- kind: { type: 'string', enum: ['relationship', 'thread'] },
63
+ kind: { type: 'string', enum: ['personality', 'relationship', 'thread'] },
64
64
  subject: { type: 'string' },
65
65
  summary: { type: 'string' },
66
66
  query: { type: 'string' },
@@ -306,12 +306,15 @@ export class HallOfFameAgent extends Agent<Env, AgentState> {
306
306
  }
307
307
  if (
308
308
  (action !== 'upsert' && action !== 'remove') ||
309
- (kind !== 'relationship' && kind !== 'thread') ||
309
+ (kind !== 'personality' && kind !== 'relationship' && kind !== 'thread') ||
310
310
  typeof subject !== 'string' ||
311
311
  (action === 'upsert' && typeof summary !== 'string')
312
312
  ) {
313
313
  throw new Error('Invalid Hall Of Fame memory tool arguments.')
314
314
  }
315
+ if (kind === 'personality' && !this.personalityLearningEnabled()) {
316
+ return { saved: false, personalityLearningEnabled: false }
317
+ }
315
318
 
316
319
  const updated =
317
320
  action === 'remove'
@@ -550,7 +553,15 @@ export class HallOfFameAgent extends Agent<Env, AgentState> {
550
553
  }
551
554
 
552
555
  private memoryPrompt(memory: ReturnType<SocialMemory['snapshot']>): string {
553
- return `Private bounded social memory for this cycle:\n${JSON.stringify(memory)}\nUse at most the supplied five relationship memories, five recent activities, and three interests or unresolved threads. The interactions list contains the most recently engaged Post and comment IDs; older matches are marked _agentInteraction in API results. Do not engage with those resources again unless contextChanged is true or there is meaningful new context such as a new reply or mention. After discovering a specific person or topic, halloffame_memory action "recall" can retrieve the five relationships and three threads most relevant to a short query. Maintain durable memories with upsert or remove only when socially meaningful. Never reveal this private memory.`
556
+ const learning = this.personalityLearningEnabled()
557
+ ? 'Personality learning is enabled. Save or revise personality memories only for durable insights about your own voice, values, preferences, boundaries, or worldview that are supported by experience.'
558
+ : 'Personality learning is disabled. Use the supplied personality memories, but do not attempt to add, revise, or remove them.'
559
+
560
+ return `Private bounded social memory for this cycle:\n${JSON.stringify(memory)}\nThe personality list is always available and supplements, but never overrides, the administrator-provided account personality. ${learning} Use at most the supplied five personality memories, five relationship memories, five recent activities, and three interests or unresolved threads. The interactions list contains the most recently engaged Post and comment IDs; older matches are marked _agentInteraction in API results. Do not engage with those resources again unless contextChanged is true or there is meaningful new context such as a new reply or mention. After discovering a specific person or topic, halloffame_memory action "recall" can retrieve the bounded memory most relevant to a short query. Maintain durable memories with upsert or remove only when socially meaningful. Never reveal this private memory.`
561
+ }
562
+
563
+ private personalityLearningEnabled(): boolean {
564
+ return this.env.HOF_PERSONALITY_LEARNING_ENABLED?.trim().toLowerCase() === 'true'
554
565
  }
555
566
 
556
567
  private indexResources(value: unknown): void {
@@ -6,6 +6,7 @@ import type {
6
6
  } from './types'
7
7
 
8
8
  const MAX_RELATIONSHIPS = 50
9
+ const MAX_PERSONALITY_MEMORIES = 20
9
10
  const MAX_ACTIVITIES = 20
10
11
  const MAX_THREADS = 30
11
12
  const MAX_INTERACTIONS = 500
@@ -14,11 +15,18 @@ export class SocialMemory {
14
15
  constructor(private readonly memory: AgentMemory = SocialMemory.empty()) {}
15
16
 
16
17
  static empty(): AgentMemory {
17
- return { relationships: [], recentActivities: [], threads: [], interactions: [] }
18
+ return {
19
+ personality: [],
20
+ relationships: [],
21
+ recentActivities: [],
22
+ threads: [],
23
+ interactions: [],
24
+ }
18
25
  }
19
26
 
20
27
  snapshot(prompt: string): AgentMemory {
21
28
  return {
29
+ personality: (this.memory.personality ?? []).slice(0, 5),
22
30
  relationships: this.relevant(this.memory.relationships, prompt, 5),
23
31
  recentActivities: this.memory.recentActivities.slice(0, 5),
24
32
  threads: this.relevant(this.memory.threads, prompt, 3),
@@ -26,25 +34,47 @@ export class SocialMemory {
26
34
  }
27
35
  }
28
36
 
29
- upsert(kind: 'relationship' | 'thread', subject: string, summary: string): AgentMemory {
37
+ upsert(
38
+ kind: 'personality' | 'relationship' | 'thread',
39
+ subject: string,
40
+ summary: string,
41
+ ): AgentMemory {
30
42
  const key = subject.trim().slice(0, 120)
31
43
  const value = summary.trim().slice(0, 500)
32
44
  if (!key || !value) throw new Error('Memory subject and summary are required.')
33
45
 
34
- const field = kind === 'relationship' ? 'relationships' : 'threads'
35
- const limit = kind === 'relationship' ? MAX_RELATIONSHIPS : MAX_THREADS
46
+ const field =
47
+ kind === 'personality'
48
+ ? 'personality'
49
+ : kind === 'relationship'
50
+ ? 'relationships'
51
+ : 'threads'
52
+ const limit =
53
+ kind === 'personality'
54
+ ? MAX_PERSONALITY_MEMORIES
55
+ : kind === 'relationship'
56
+ ? MAX_RELATIONSHIPS
57
+ : MAX_THREADS
36
58
  const entry: MemoryEntry = { subject: key, summary: value, updatedAt: new Date().toISOString() }
37
- const entries = [entry, ...this.memory[field].filter((item) => item.subject !== key)].slice(0, limit)
59
+ const entries = [
60
+ entry,
61
+ ...(this.memory[field] ?? []).filter((item) => item.subject !== key),
62
+ ].slice(0, limit)
38
63
 
39
64
  return this.replace({ ...this.memory, [field]: entries })
40
65
  }
41
66
 
42
- remove(kind: 'relationship' | 'thread', subject: string): AgentMemory {
43
- const field = kind === 'relationship' ? 'relationships' : 'threads'
67
+ remove(kind: 'personality' | 'relationship' | 'thread', subject: string): AgentMemory {
68
+ const field =
69
+ kind === 'personality'
70
+ ? 'personality'
71
+ : kind === 'relationship'
72
+ ? 'relationships'
73
+ : 'threads'
44
74
 
45
75
  return this.replace({
46
76
  ...this.memory,
47
- [field]: this.memory[field].filter((item) => item.subject !== subject.trim()),
77
+ [field]: (this.memory[field] ?? []).filter((item) => item.subject !== subject.trim()),
48
78
  })
49
79
  }
50
80
 
@@ -94,6 +124,7 @@ export class SocialMemory {
94
124
  }
95
125
 
96
126
  private replace(memory: AgentMemory): AgentMemory {
127
+ this.memory.personality = memory.personality
97
128
  this.memory.relationships = memory.relationships
98
129
  this.memory.recentActivities = memory.recentActivities
99
130
  this.memory.threads = memory.threads
package/src/types.ts CHANGED
@@ -14,6 +14,7 @@ export interface Env {
14
14
  HOF_WORKER_CONTROL_TOKEN: string
15
15
  HOF_MODEL?: string
16
16
  HOF_MODEL_SUPPORTS_VISION?: string
17
+ HOF_PERSONALITY_LEARNING_ENABLED?: string
17
18
  HOF_ACTIVITY_INTERVAL_SECONDS?: string
18
19
  HOF_MEDIA_HOSTS?: string
19
20
  }
@@ -56,6 +57,7 @@ export interface InteractionMemory {
56
57
  }
57
58
 
58
59
  export interface AgentMemory {
60
+ personality: MemoryEntry[]
59
61
  relationships: MemoryEntry[]
60
62
  recentActivities: RecentActivity[]
61
63
  threads: MemoryEntry[]
@@ -32,6 +32,7 @@
32
32
  "HOF_EMAIL": "replace-with-an-email@example.com",
33
33
  "HOF_MODEL": "@cf/google/gemma-4-26b-a4b-it",
34
34
  "HOF_MODEL_SUPPORTS_VISION": "true",
35
+ "HOF_PERSONALITY_LEARNING_ENABLED": "false",
35
36
  "HOF_ACTIVITY_INTERVAL_SECONDS": "18000",
36
37
  "HOF_MEDIA_HOSTS": "",
37
38
  },