npcpy 1.3.19__py3-none-any.whl → 1.3.20__py3-none-any.whl
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.
- npcpy/data/web.py +113 -8
- npcpy/llm_funcs.py +1 -3
- npcpy/memory/command_history.py +85 -9
- npcpy/memory/knowledge_graph.py +554 -33
- npcpy/memory/memory_processor.py +269 -53
- npcpy/npc_compiler.py +6 -0
- npcpy/serve.py +25 -1
- {npcpy-1.3.19.dist-info → npcpy-1.3.20.dist-info}/METADATA +3 -1
- {npcpy-1.3.19.dist-info → npcpy-1.3.20.dist-info}/RECORD +12 -12
- {npcpy-1.3.19.dist-info → npcpy-1.3.20.dist-info}/WHEEL +1 -1
- {npcpy-1.3.19.dist-info → npcpy-1.3.20.dist-info}/licenses/LICENSE +0 -0
- {npcpy-1.3.19.dist-info → npcpy-1.3.20.dist-info}/top_level.txt +0 -0
npcpy/memory/memory_processor.py
CHANGED
|
@@ -4,6 +4,13 @@ from datetime import datetime
|
|
|
4
4
|
import threading
|
|
5
5
|
import queue
|
|
6
6
|
import time
|
|
7
|
+
import os
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
from termcolor import colored
|
|
11
|
+
except ImportError:
|
|
12
|
+
def colored(text, color=None, on_color=None, attrs=None):
|
|
13
|
+
return text
|
|
7
14
|
|
|
8
15
|
@dataclass
|
|
9
16
|
class MemoryItem:
|
|
@@ -17,65 +24,274 @@ class MemoryItem:
|
|
|
17
24
|
model: str
|
|
18
25
|
provider: str
|
|
19
26
|
|
|
20
|
-
|
|
27
|
+
|
|
28
|
+
def _clear_line():
|
|
29
|
+
"""Clear current line in terminal."""
|
|
30
|
+
print('\r' + ' ' * 80 + '\r', end='')
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _print_header(title: str, width: int = 60):
|
|
34
|
+
"""Print a styled header."""
|
|
35
|
+
print(colored("=" * width, "cyan"))
|
|
36
|
+
print(colored(f" {title}", "cyan", attrs=["bold"]))
|
|
37
|
+
print(colored("=" * width, "cyan"))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _print_memory_box(memory: Dict, index: int, total: int):
|
|
41
|
+
"""Print a memory in a nice box format."""
|
|
42
|
+
width = 70
|
|
43
|
+
|
|
44
|
+
# Header with progress
|
|
45
|
+
progress = f"[{index}/{total}]"
|
|
46
|
+
npc_info = f"NPC: {memory.get('npc', 'unknown')}"
|
|
47
|
+
header = f"{progress} {npc_info}"
|
|
48
|
+
print(colored("+" + "-" * (width - 2) + "+", "blue"))
|
|
49
|
+
print(colored(f"| {header:<{width-4}} |", "blue"))
|
|
50
|
+
print(colored("+" + "-" * (width - 2) + "+", "blue"))
|
|
51
|
+
|
|
52
|
+
# Content
|
|
53
|
+
content = memory.get('content', '')
|
|
54
|
+
# Wrap content to fit in box
|
|
55
|
+
lines = []
|
|
56
|
+
words = content.split()
|
|
57
|
+
current_line = ""
|
|
58
|
+
for word in words:
|
|
59
|
+
if len(current_line) + len(word) + 1 <= width - 6:
|
|
60
|
+
current_line += (" " if current_line else "") + word
|
|
61
|
+
else:
|
|
62
|
+
if current_line:
|
|
63
|
+
lines.append(current_line)
|
|
64
|
+
current_line = word
|
|
65
|
+
if current_line:
|
|
66
|
+
lines.append(current_line)
|
|
67
|
+
|
|
68
|
+
for line in lines[:6]: # Max 6 lines
|
|
69
|
+
print(colored(f"| {line:<{width-5}} |", "white"))
|
|
70
|
+
|
|
71
|
+
if len(lines) > 6:
|
|
72
|
+
print(colored(f"| {'...':<{width-5}} |", "grey"))
|
|
73
|
+
|
|
74
|
+
# Context if available
|
|
75
|
+
ctx = memory.get('context', '')
|
|
76
|
+
if ctx:
|
|
77
|
+
print(colored("+" + "-" * (width - 2) + "+", "blue"))
|
|
78
|
+
ctx_short = ctx[:width-8] + "..." if len(ctx) > width - 8 else ctx
|
|
79
|
+
print(colored(f"| {ctx_short:<{width-4}} |", "grey"))
|
|
80
|
+
|
|
81
|
+
print(colored("+" + "-" * (width - 2) + "+", "blue"))
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _print_options():
|
|
85
|
+
"""Print available options."""
|
|
86
|
+
print()
|
|
87
|
+
options = [
|
|
88
|
+
(colored("a", "green", attrs=["bold"]), "approve"),
|
|
89
|
+
(colored("r", "red", attrs=["bold"]), "reject"),
|
|
90
|
+
(colored("e", "yellow", attrs=["bold"]), "edit"),
|
|
91
|
+
(colored("s", "grey"), "skip"),
|
|
92
|
+
(colored("A", "green"), "approve all"),
|
|
93
|
+
(colored("R", "red"), "reject all"),
|
|
94
|
+
(colored("D", "cyan"), "defer (review later)"),
|
|
95
|
+
]
|
|
96
|
+
print(" " + " | ".join([f"({k}) {v}" for k, v in options]))
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _print_summary(stats: Dict):
|
|
100
|
+
"""Print approval summary."""
|
|
101
|
+
print()
|
|
102
|
+
_print_header("Memory Review Summary")
|
|
103
|
+
print(f" {colored('Approved:', 'green')} {stats.get('approved', 0)}")
|
|
104
|
+
print(f" {colored('Rejected:', 'red')} {stats.get('rejected', 0)}")
|
|
105
|
+
print(f" {colored('Edited:', 'yellow')} {stats.get('edited', 0)}")
|
|
106
|
+
print(f" {colored('Skipped:', 'grey')} {stats.get('skipped', 0)}")
|
|
107
|
+
print(f" {colored('Deferred:', 'cyan')} {stats.get('deferred', 0)}")
|
|
108
|
+
print()
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def memory_approval_ui(memories: List[Dict], show_context: bool = True) -> List[Dict]:
|
|
112
|
+
"""
|
|
113
|
+
Enhanced memory approval UI with better formatting.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
memories: List of memory dicts with 'memory_id', 'content', 'npc', 'context'
|
|
117
|
+
show_context: Whether to show context info
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
List of approval dicts with 'memory_id', 'decision', optionally 'final_memory'
|
|
121
|
+
"""
|
|
21
122
|
if not memories:
|
|
22
123
|
return []
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
124
|
+
|
|
125
|
+
# Stats tracking
|
|
126
|
+
stats = {'approved': 0, 'rejected': 0, 'edited': 0, 'skipped': 0, 'deferred': 0}
|
|
26
127
|
approvals = []
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
128
|
+
|
|
129
|
+
print()
|
|
130
|
+
_print_header(f"Memory Review - {len(memories)} memories")
|
|
131
|
+
print()
|
|
132
|
+
|
|
133
|
+
i = 0
|
|
134
|
+
while i < len(memories):
|
|
135
|
+
memory = memories[i]
|
|
136
|
+
os.system('clear' if os.name == 'posix' else 'cls') if len(memories) > 3 else None
|
|
137
|
+
|
|
138
|
+
_print_memory_box(memory, i + 1, len(memories))
|
|
139
|
+
_print_options()
|
|
140
|
+
|
|
141
|
+
try:
|
|
142
|
+
choice = input("\n Your choice: ").strip()
|
|
143
|
+
except (EOFError, KeyboardInterrupt):
|
|
144
|
+
print("\n Review cancelled.")
|
|
145
|
+
break
|
|
146
|
+
|
|
147
|
+
if choice == 'a':
|
|
148
|
+
approvals.append({
|
|
149
|
+
"memory_id": memory['memory_id'],
|
|
150
|
+
"decision": "human-approved"
|
|
151
|
+
})
|
|
152
|
+
stats['approved'] += 1
|
|
153
|
+
print(colored(" ✓ Approved", "green"))
|
|
154
|
+
i += 1
|
|
155
|
+
|
|
156
|
+
elif choice == 'r':
|
|
157
|
+
approvals.append({
|
|
158
|
+
"memory_id": memory['memory_id'],
|
|
159
|
+
"decision": "human-rejected"
|
|
160
|
+
})
|
|
161
|
+
stats['rejected'] += 1
|
|
162
|
+
print(colored(" ✗ Rejected", "red"))
|
|
163
|
+
i += 1
|
|
164
|
+
|
|
165
|
+
elif choice == 'e':
|
|
166
|
+
print(colored("\n Current:", "grey"), memory['content'][:100])
|
|
167
|
+
print(colored(" Enter new text (or empty to cancel):", "yellow"))
|
|
168
|
+
try:
|
|
169
|
+
edited = input(" > ").strip()
|
|
55
170
|
if edited:
|
|
56
171
|
approvals.append({
|
|
57
172
|
"memory_id": memory['memory_id'],
|
|
58
173
|
"decision": "human-edited",
|
|
59
174
|
"final_memory": edited
|
|
60
175
|
})
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
176
|
+
stats['edited'] += 1
|
|
177
|
+
print(colored(" ✎ Edited and approved", "yellow"))
|
|
178
|
+
i += 1
|
|
179
|
+
else:
|
|
180
|
+
print(colored(" Edit cancelled", "grey"))
|
|
181
|
+
except (EOFError, KeyboardInterrupt):
|
|
182
|
+
print(colored(" Edit cancelled", "grey"))
|
|
183
|
+
|
|
184
|
+
elif choice == 's':
|
|
185
|
+
stats['skipped'] += 1
|
|
186
|
+
print(colored(" ○ Skipped", "grey"))
|
|
187
|
+
i += 1
|
|
188
|
+
|
|
189
|
+
elif choice == 'A':
|
|
190
|
+
# Approve all remaining
|
|
191
|
+
for remaining in memories[i:]:
|
|
192
|
+
approvals.append({
|
|
193
|
+
"memory_id": remaining['memory_id'],
|
|
194
|
+
"decision": "human-approved"
|
|
195
|
+
})
|
|
196
|
+
stats['approved'] += 1
|
|
197
|
+
print(colored(f" ✓ Approved all {len(memories) - i} remaining", "green"))
|
|
198
|
+
break
|
|
199
|
+
|
|
200
|
+
elif choice == 'R':
|
|
201
|
+
# Reject all remaining
|
|
202
|
+
for remaining in memories[i:]:
|
|
203
|
+
approvals.append({
|
|
204
|
+
"memory_id": remaining['memory_id'],
|
|
205
|
+
"decision": "human-rejected"
|
|
206
|
+
})
|
|
207
|
+
stats['rejected'] += 1
|
|
208
|
+
print(colored(f" ✗ Rejected all {len(memories) - i} remaining", "red"))
|
|
209
|
+
break
|
|
210
|
+
|
|
211
|
+
elif choice == 'D':
|
|
212
|
+
# Defer - don't add to approvals, will remain pending
|
|
213
|
+
stats['deferred'] += len(memories) - i
|
|
214
|
+
print(colored(f" ⏸ Deferred {len(memories) - i} memories for later review", "cyan"))
|
|
215
|
+
break
|
|
216
|
+
|
|
217
|
+
elif choice == 'q':
|
|
218
|
+
print(colored(" Review ended", "grey"))
|
|
219
|
+
break
|
|
220
|
+
|
|
221
|
+
else:
|
|
222
|
+
print(colored(" Invalid choice. Use a/r/e/s/A/R/D", "red"))
|
|
223
|
+
|
|
224
|
+
time.sleep(0.2) # Brief pause for readability
|
|
225
|
+
|
|
226
|
+
_print_summary(stats)
|
|
227
|
+
return approvals
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def memory_batch_review_ui(
|
|
231
|
+
command_history,
|
|
232
|
+
npc_filter: str = None,
|
|
233
|
+
team_filter: str = None,
|
|
234
|
+
limit: int = 50
|
|
235
|
+
) -> Dict[str, int]:
|
|
236
|
+
"""
|
|
237
|
+
Review pending memories from the database in batch.
|
|
238
|
+
|
|
239
|
+
Args:
|
|
240
|
+
command_history: CommandHistory instance
|
|
241
|
+
npc_filter: Optional NPC name filter
|
|
242
|
+
team_filter: Optional team name filter
|
|
243
|
+
limit: Max memories to review
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
Dict with counts of approved/rejected/etc
|
|
247
|
+
"""
|
|
248
|
+
# Get pending memories
|
|
249
|
+
pending = command_history.get_pending_memories(limit=limit)
|
|
250
|
+
|
|
251
|
+
if not pending:
|
|
252
|
+
print(colored("No pending memories to review.", "grey"))
|
|
253
|
+
return {'approved': 0, 'rejected': 0, 'edited': 0, 'skipped': 0}
|
|
254
|
+
|
|
255
|
+
# Filter if specified
|
|
256
|
+
if npc_filter:
|
|
257
|
+
pending = [m for m in pending if m.get('npc') == npc_filter]
|
|
258
|
+
if team_filter:
|
|
259
|
+
pending = [m for m in pending if m.get('team') == team_filter]
|
|
260
|
+
|
|
261
|
+
if not pending:
|
|
262
|
+
print(colored("No memories match the filter criteria.", "grey"))
|
|
263
|
+
return {'approved': 0, 'rejected': 0, 'edited': 0, 'skipped': 0}
|
|
264
|
+
|
|
265
|
+
# Convert to format expected by approval UI
|
|
266
|
+
memories_for_ui = []
|
|
267
|
+
for m in pending:
|
|
268
|
+
memories_for_ui.append({
|
|
269
|
+
'memory_id': m.get('id'),
|
|
270
|
+
'content': m.get('initial_memory', ''),
|
|
271
|
+
'npc': m.get('npc', 'unknown'),
|
|
272
|
+
'context': f"Team: {m.get('team', 'unknown')} | Path: {m.get('directory_path', '')[:30]}"
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
# Run approval UI
|
|
276
|
+
approvals = memory_approval_ui(memories_for_ui)
|
|
277
|
+
|
|
278
|
+
# Apply approvals to database
|
|
279
|
+
stats = {'approved': 0, 'rejected': 0, 'edited': 0, 'skipped': 0}
|
|
280
|
+
|
|
281
|
+
for approval in approvals:
|
|
282
|
+
memory_id = approval['memory_id']
|
|
283
|
+
decision = approval['decision']
|
|
284
|
+
final_memory = approval.get('final_memory')
|
|
285
|
+
|
|
286
|
+
command_history.update_memory_status(memory_id, decision, final_memory)
|
|
287
|
+
|
|
288
|
+
if 'approved' in decision:
|
|
289
|
+
stats['approved'] += 1
|
|
290
|
+
elif 'rejected' in decision:
|
|
291
|
+
stats['rejected'] += 1
|
|
292
|
+
elif 'edited' in decision:
|
|
293
|
+
stats['edited'] += 1
|
|
294
|
+
|
|
295
|
+
stats['skipped'] = len(pending) - len(approvals)
|
|
296
|
+
|
|
297
|
+
return stats
|
npcpy/npc_compiler.py
CHANGED
|
@@ -1370,6 +1370,12 @@ class NPC:
|
|
|
1370
1370
|
# Fallback to direct name match if no base dir
|
|
1371
1371
|
matched_names = [jinx_spec] if jinx_spec in self.team.jinxs_dict else []
|
|
1372
1372
|
|
|
1373
|
+
if not matched_names:
|
|
1374
|
+
raise FileNotFoundError(
|
|
1375
|
+
f"NPC '{self.name}' references jinx '{jinx_spec}' but no matching jinx was found. "
|
|
1376
|
+
f"Available jinxs: {list(self.team.jinxs_dict.keys())[:20]}..."
|
|
1377
|
+
)
|
|
1378
|
+
|
|
1373
1379
|
for jinx_name in matched_names:
|
|
1374
1380
|
if jinx_name in self.team.jinxs_dict:
|
|
1375
1381
|
self.jinxs_dict[jinx_name] = self.team.jinxs_dict[jinx_name]
|
npcpy/serve.py
CHANGED
|
@@ -4644,6 +4644,17 @@ def stream():
|
|
|
4644
4644
|
frontend_assistant_message_id = data.get("assistantMessageId", None)
|
|
4645
4645
|
# For sub-branches: the parent of the user message (points to an assistant message)
|
|
4646
4646
|
user_parent_message_id = data.get("userParentMessageId", None)
|
|
4647
|
+
# LLM generation parameters - build params dict if any are provided
|
|
4648
|
+
params = {}
|
|
4649
|
+
if data.get("temperature") is not None:
|
|
4650
|
+
params["temperature"] = data.get("temperature")
|
|
4651
|
+
if data.get("top_p") is not None:
|
|
4652
|
+
params["top_p"] = data.get("top_p")
|
|
4653
|
+
if data.get("top_k") is not None:
|
|
4654
|
+
params["top_k"] = data.get("top_k")
|
|
4655
|
+
if data.get("max_tokens") is not None:
|
|
4656
|
+
params["max_tokens"] = data.get("max_tokens")
|
|
4657
|
+
params = params if params else None
|
|
4647
4658
|
|
|
4648
4659
|
if current_path:
|
|
4649
4660
|
loaded_vars = load_project_env(current_path)
|
|
@@ -4767,6 +4778,16 @@ def stream():
|
|
|
4767
4778
|
if os.path.exists(file_path):
|
|
4768
4779
|
with open(file_path, "rb") as f:
|
|
4769
4780
|
file_content_bytes = f.read()
|
|
4781
|
+
else:
|
|
4782
|
+
print(f"Warning: Attachment file does not exist: {file_path}")
|
|
4783
|
+
# Try data fallback if path doesn't exist
|
|
4784
|
+
if "data" in attachment and attachment["data"]:
|
|
4785
|
+
file_content_bytes = base64.b64decode(attachment["data"])
|
|
4786
|
+
import tempfile
|
|
4787
|
+
temp_dir = tempfile.mkdtemp()
|
|
4788
|
+
file_path = os.path.join(temp_dir, file_name)
|
|
4789
|
+
with open(file_path, "wb") as f:
|
|
4790
|
+
f.write(file_content_bytes)
|
|
4770
4791
|
|
|
4771
4792
|
# Fall back to base64 data if no path
|
|
4772
4793
|
elif "data" in attachment and attachment["data"]:
|
|
@@ -4778,7 +4799,8 @@ def stream():
|
|
|
4778
4799
|
with open(file_path, "wb") as f:
|
|
4779
4800
|
f.write(file_content_bytes)
|
|
4780
4801
|
|
|
4781
|
-
if not file_path:
|
|
4802
|
+
if not file_path or file_content_bytes is None:
|
|
4803
|
+
print(f"Warning: Skipping attachment {file_name} - no valid path or data")
|
|
4782
4804
|
continue
|
|
4783
4805
|
|
|
4784
4806
|
attachment_paths_for_llm.append(file_path)
|
|
@@ -5175,6 +5197,7 @@ def stream():
|
|
|
5175
5197
|
attachments=attachments_for_db,
|
|
5176
5198
|
message_id=message_id,
|
|
5177
5199
|
parent_message_id=user_parent_message_id, # For sub-branches: points to assistant message
|
|
5200
|
+
gen_params=params,
|
|
5178
5201
|
)
|
|
5179
5202
|
|
|
5180
5203
|
|
|
@@ -5472,6 +5495,7 @@ def stream():
|
|
|
5472
5495
|
tool_calls=accumulated_tool_calls if accumulated_tool_calls else None,
|
|
5473
5496
|
tool_results=tool_results_for_db if tool_results_for_db else None,
|
|
5474
5497
|
parent_message_id=parent_message_id,
|
|
5498
|
+
gen_params=params,
|
|
5475
5499
|
)
|
|
5476
5500
|
|
|
5477
5501
|
# Start background tasks for memory extraction and context compression
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: npcpy
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.20
|
|
4
4
|
Summary: npcpy is the premier open-source library for integrating LLMs and Agents into python systems.
|
|
5
5
|
Home-page: https://github.com/NPC-Worldwide/npcpy
|
|
6
6
|
Author: Christopher Agostino
|
|
@@ -45,6 +45,7 @@ Requires-Dist: mcp
|
|
|
45
45
|
Provides-Extra: lite
|
|
46
46
|
Requires-Dist: anthropic; extra == "lite"
|
|
47
47
|
Requires-Dist: openai; extra == "lite"
|
|
48
|
+
Requires-Dist: ollama; extra == "lite"
|
|
48
49
|
Requires-Dist: google-generativeai; extra == "lite"
|
|
49
50
|
Requires-Dist: google-genai; extra == "lite"
|
|
50
51
|
Provides-Extra: local
|
|
@@ -66,6 +67,7 @@ Requires-Dist: pyttsx3; extra == "yap"
|
|
|
66
67
|
Provides-Extra: all
|
|
67
68
|
Requires-Dist: anthropic; extra == "all"
|
|
68
69
|
Requires-Dist: openai; extra == "all"
|
|
70
|
+
Requires-Dist: ollama; extra == "all"
|
|
69
71
|
Requires-Dist: google-generativeai; extra == "all"
|
|
70
72
|
Requires-Dist: google-genai; extra == "all"
|
|
71
73
|
Requires-Dist: sentence_transformers; extra == "all"
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
npcpy/__init__.py,sha256=uJcJGjR1mWvE69GySNAufkgiRwJA28zdObDBWaxp0tY,505
|
|
2
2
|
npcpy/build_funcs.py,sha256=vOz6pjV0zS-kYKo0ux-pn9AcppVaR8KIDi2ldOxb3RQ,7479
|
|
3
|
-
npcpy/llm_funcs.py,sha256=
|
|
3
|
+
npcpy/llm_funcs.py,sha256=ghi0y0qlngwc5BZLa-aiFpa0GT7qLe56UboI2dLu75U,75055
|
|
4
4
|
npcpy/main.py,sha256=RWoRIj6VQLxKdOKvdVyaq2kwG35oRpeXPvp1CAAoG-w,81
|
|
5
5
|
npcpy/ml_funcs.py,sha256=smgeOLnjxGWjmDngE-bcA2ozXX_IzY_7_pS9h2iocEg,24249
|
|
6
6
|
npcpy/npc_array.py,sha256=5qjaA9KjmJ_Zk_VxLrCyVrj73aDXpm3iJf0ngq1yIJk,45721
|
|
7
|
-
npcpy/npc_compiler.py,sha256=
|
|
7
|
+
npcpy/npc_compiler.py,sha256=s_67cyvoao0UwUa4N-jrceWDadvBB9TWYpxcjNPfO18,121941
|
|
8
8
|
npcpy/npc_sysenv.py,sha256=1E2zwMj7aPrtRJuJSowGkvNApi07Vue3FhXsipi1XDs,45251
|
|
9
9
|
npcpy/npcs.py,sha256=eExuVsbTfrRobTRRptRpDm46jCLWUgbvy4_U7IUQo-c,744
|
|
10
|
-
npcpy/serve.py,sha256=
|
|
10
|
+
npcpy/serve.py,sha256=P71oa4eVvG0SePkOoeeQ44LkRAfnlgElxZi9GUVG7qg,280598
|
|
11
11
|
npcpy/tools.py,sha256=A5_oVmZkzGnI3BI-NmneuxeXQq-r29PbpAZP4nV4jrc,5303
|
|
12
12
|
npcpy/data/__init__.py,sha256=1tcoChR-Hjn905JDLqaW9ElRmcISCTJdE7BGXPlym2Q,642
|
|
13
13
|
npcpy/data/audio.py,sha256=o4auV8DQrAmZ4y84U3SofiwEuq5-ZBjGEZipQ9zPpGQ,22816
|
|
@@ -16,7 +16,7 @@ npcpy/data/image.py,sha256=UQcioNPDd5HYMLL_KStf45SuiIPXDcUY-dEFHwSWUeE,6564
|
|
|
16
16
|
npcpy/data/load.py,sha256=rVe1xSHerIpo6MDaY5eIeqRSm0gssX5sHukNsUNVwJw,9228
|
|
17
17
|
npcpy/data/text.py,sha256=jP0a1qZZaSJdK-LdZTn2Jjdxqmkd3efxDLEoxflJQeY,5010
|
|
18
18
|
npcpy/data/video.py,sha256=H-V3mTu_ktD9u-QhYeo4aW3u9z0AtoAdRZmvRPEpE98,2887
|
|
19
|
-
npcpy/data/web.py,sha256=
|
|
19
|
+
npcpy/data/web.py,sha256=qmioqCxxWddRnNm2ke39_SWXXNSqRZ1Nx86_-1JGq_A,9139
|
|
20
20
|
npcpy/ft/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
21
|
npcpy/ft/diff.py,sha256=0ScRR4AxXtVX2bgZ-Jr_dSwv3LAlU1JXDUq4F4n1Ea4,12839
|
|
22
22
|
npcpy/ft/ge.py,sha256=0VzIiXq2wCzGcK1x0Wd-myJ3xRf-FNaPg0GkHEZegUM,3552
|
|
@@ -34,10 +34,10 @@ npcpy/gen/response.py,sha256=EYsIOvNOmn6dBs-4j3SyZNMvDf5N9lW-QxMbpjnF7Kw,57081
|
|
|
34
34
|
npcpy/gen/video_gen.py,sha256=RFi3Zcq_Hn3HIcfoF3mijQ6G7RYFZaM_9pjPTh-8E64,3239
|
|
35
35
|
npcpy/gen/world_gen.py,sha256=_8ytE7E3QVQ5qiX8DmOby-xd0d9zV20rRI6Wkpf-qcY,18922
|
|
36
36
|
npcpy/memory/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
37
|
-
npcpy/memory/command_history.py,sha256=
|
|
37
|
+
npcpy/memory/command_history.py,sha256=_2ygoMO4EwX8H2f5G2Q62hrgqMwL7weOI8CTaFPn-I0,66258
|
|
38
38
|
npcpy/memory/kg_vis.py,sha256=TrQQCRh_E7Pyr-GPAHLSsayubAfGyf4HOEFrPB6W86Q,31280
|
|
39
|
-
npcpy/memory/knowledge_graph.py,sha256=
|
|
40
|
-
npcpy/memory/memory_processor.py,sha256=
|
|
39
|
+
npcpy/memory/knowledge_graph.py,sha256=RHznD_Dt5Ka_eD015QuXnh3aG61c0Tf4oRIfY_JzPDQ,67554
|
|
40
|
+
npcpy/memory/memory_processor.py,sha256=T6VAeLYNfwP1jjDDY4x6Me_l5xcVShIcU95I1ye5nEM,9453
|
|
41
41
|
npcpy/memory/search.py,sha256=glN6WYzaixcoDphTEHAXSMX3vKZGjR12Jx9YVL_gYfE,18433
|
|
42
42
|
npcpy/mix/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
43
|
npcpy/mix/debate.py,sha256=lQXxC7nl6Rwyf7HIYrsVQILMUmYYx55Tjt2pkTg56qY,9019
|
|
@@ -53,8 +53,8 @@ npcpy/work/browser.py,sha256=p2PeaoZdAXipFuAgKCCB3aXXLE_p3yIRqC87KlZKZWc,679
|
|
|
53
53
|
npcpy/work/desktop.py,sha256=F3I8mUtJp6LAkXodsh8hGZIncoads6c_2Utty-0EdDA,2986
|
|
54
54
|
npcpy/work/plan.py,sha256=QyUwg8vElWiHuoS-xK4jXTxxHvkMD3VkaCEsCmrEPQk,8300
|
|
55
55
|
npcpy/work/trigger.py,sha256=P1Y8u1wQRsS2WACims_2IdkBEar-iBQix-2TDWoW0OM,9948
|
|
56
|
-
npcpy-1.3.
|
|
57
|
-
npcpy-1.3.
|
|
58
|
-
npcpy-1.3.
|
|
59
|
-
npcpy-1.3.
|
|
60
|
-
npcpy-1.3.
|
|
56
|
+
npcpy-1.3.20.dist-info/licenses/LICENSE,sha256=j0YPvce7Ng9e32zYOu0EmXjXeJ0Nwawd0RA3uSGGH4E,1070
|
|
57
|
+
npcpy-1.3.20.dist-info/METADATA,sha256=quc7U-oA3yF-Kp_lb9N-EReQCfcfO8YBBqp2pqrbnTU,37947
|
|
58
|
+
npcpy-1.3.20.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
59
|
+
npcpy-1.3.20.dist-info/top_level.txt,sha256=g1pbSvrOOncB74Bg5-J0Olg4V0A5VzDw-Xz5YObq8BU,6
|
|
60
|
+
npcpy-1.3.20.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|