nuagent 0.2.3__tar.gz → 0.2.5__tar.gz

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.
Files changed (29) hide show
  1. {nuagent-0.2.3 → nuagent-0.2.5}/PKG-INFO +4 -4
  2. {nuagent-0.2.3 → nuagent-0.2.5}/pyproject.toml +4 -4
  3. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/__init__.py +1 -1
  4. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/core/loop.py +1 -1
  5. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/planes/chat.py +27 -12
  6. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/planes/engine.py +1 -1
  7. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/planes/settings.py +4 -3
  8. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/presets/backends/cc.py +1 -1
  9. {nuagent-0.2.3 → nuagent-0.2.5}/.gitignore +0 -0
  10. {nuagent-0.2.3 → nuagent-0.2.5}/README.md +0 -0
  11. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/core/__init__.py +0 -0
  12. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/core/program.py +0 -0
  13. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/planes/__init__.py +0 -0
  14. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/planes/ext.py +0 -0
  15. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/planes/state.py +0 -0
  16. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/planes/store.py +0 -0
  17. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/presets/__init__.py +0 -0
  18. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/presets/backends/__init__.py +0 -0
  19. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/presets/backends/llm.py +0 -0
  20. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/presets/store/__init__.py +0 -0
  21. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/presets/store/kv.py +0 -0
  22. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/presets/store/mem.py +0 -0
  23. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/prompt/__init__.py +0 -0
  24. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/prompt/catalogue.py +0 -0
  25. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/prompt/section.py +0 -0
  26. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/prompt/surface.py +0 -0
  27. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/protocol/__init__.py +0 -0
  28. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/protocol/observation.py +0 -0
  29. {nuagent-0.2.3 → nuagent-0.2.5}/src/nuagent/protocol/protocol.md +0 -0
@@ -1,20 +1,20 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: nuagent
3
- Version: 0.2.3
3
+ Version: 0.2.5
4
4
  Summary: nuagent: the model answers in Nu, Nu runs the answer.
5
5
  Project-URL: Repository, https://github.com/nustackdev/nuverse
6
6
  Author-email: Gor Arakelyan <gorarkln@gmail.com>
7
7
  License-Expression: Apache-2.0
8
8
  Requires-Python: >=3.10
9
- Requires-Dist: nucore>=0.6.5
9
+ Requires-Dist: nucore>=0.7.1
10
10
  Requires-Dist: nuskills>=0.2.0
11
- Requires-Dist: nustd[kv]>=0.6.5
11
+ Requires-Dist: nustd[kv]>=0.7.1
12
12
  Provides-Extra: cc
13
13
  Requires-Dist: nustd[cc]; extra == 'cc'
14
14
  Provides-Extra: llm
15
15
  Requires-Dist: nustd[llm]; extra == 'llm'
16
16
  Provides-Extra: space
17
- Requires-Dist: nuspace>=0.5.7; extra == 'space'
17
+ Requires-Dist: nuspace>=0.6.4; extra == 'space'
18
18
  Description-Content-Type: text/markdown
19
19
 
20
20
  # nuagent
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "nuagent"
7
- version = "0.2.3"
7
+ version = "0.2.5"
8
8
  description = "nuagent: the model answers in Nu, Nu runs the answer."
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -12,8 +12,8 @@ authors = [{ name = "Gor Arakelyan", email = "gorarkln@gmail.com" }]
12
12
  requires-python = ">=3.10"
13
13
  dependencies = [
14
14
  # The core needs only nu. The Chat plane for nuspace is the ``space`` extra.
15
- "nucore>=0.6.5",
16
- "nustd[kv]>=0.6.5",
15
+ "nucore>=0.7.1",
16
+ "nustd[kv]>=0.7.1",
17
17
  # The generic Nu prose the opening prompt is assembled from.
18
18
  "nuskills>=0.2.0",
19
19
  ]
@@ -29,7 +29,7 @@ llm = [
29
29
  ]
30
30
  # The Chat plane, a nuspace extension: a conversation with an agent in a space.
31
31
  space = [
32
- "nuspace>=0.5.7",
32
+ "nuspace>=0.6.4",
33
33
  ]
34
34
 
35
35
  [project.urls]
@@ -21,7 +21,7 @@ if TYPE_CHECKING:
21
21
 
22
22
  __all__ = ["__version__", "extension"]
23
23
 
24
- __version__ = "0.2.3"
24
+ __version__ = "0.2.5"
25
25
 
26
26
 
27
27
  def extension() -> Extension:
@@ -132,7 +132,7 @@ def seed(store: Store, prompt: StrArg) -> Nu:
132
132
 
133
133
  Notes:
134
134
  - ``done`` is written False before the first turn. Unset it reads
135
- EMPTY, the loop condition is never true, and no turn runs.
135
+ NULL, the loop condition is never true, and no turn runs.
136
136
  """
137
137
  opening = nu.Dict.of(role="user", content=prompt)
138
138
  return store.bracket(store.session.messages.set(nu.List.of(opening))) >> store.rewrite(
@@ -30,15 +30,16 @@ import nustd.ui
30
30
  from nu.lang import ScalarQuery
31
31
  from nuagent.protocol import CONSTRUCT, NO_CODE, OK, RUNTIME
32
32
  from nuspace import ops
33
+ from nuspace.ops.kernel import plane_live
33
34
  from nuspace.ops.utils import MintId
34
- from nuspace.shapes import Reroot, Space
35
+ from nuspace.shapes import Reroot
35
36
  from nuspace.system.devices.web.shell import Shell
36
37
  from nuspace.system.devices.web.utils import CellRoot
37
- from nuspace.system.services import enable_react
38
- from nuspace.system.utils import redraws, snap
38
+ from nuspace.system.services import enable_react, up_plane
39
+ from nuspace.system.utils import snap
39
40
 
40
41
  from . import settings
41
- from .engine import IMPORTS, MADE_BY, SOURCE, engine_cell, engine_of, inbox_change
42
+ from .engine import IMPORTS, MADE_BY, SOURCE, engine_cell, engine_of, inbox_change, pending
42
43
  from .ext import said_prog
43
44
  from .state import ERROR, IDLE, RUNNING, STOPPED, THINKING, Chat
44
45
 
@@ -88,7 +89,7 @@ TITLES = {
88
89
 
89
90
 
90
91
  def ensure(page: nu.StrArg) -> nu.Nu:
91
- """The page's engine, its cell, its reaction and the agent settings, each made when missing.
92
+ """The page's engine, its cell, its lists, its reaction and the agent settings, each made when missing.
92
93
 
93
94
  Idempotent, and safe from two tabs at once: the engine and its cell
94
95
  have fixed ids, and the reaction is :func:`enable_react`'s, which is
@@ -106,8 +107,17 @@ def ensure(page: nu.StrArg) -> nu.Nu:
106
107
  snap(ops.cell_exists(cell).not_()),
107
108
  ops.add_cell(engine, SOURCE, cell_id=cell, name="engine"),
108
109
  )
110
+ # The conversation's lists, made with it: the page and the engine read them from the start.
111
+ lists = Chat.inbox.init(nu.List.create()) >> Chat.turns.init(nu.List.create())
112
+ lists = lists >> Chat.messages.init(nu.List.create())
113
+ kept = ops.atomic_state(ops.plane_state(engine, lists))
109
114
  reaction = enable_react(inbox_change(engine), engine, imports=IMPORTS)
110
- return made >> settings.ensure() >> reaction
115
+ # A reaction fires on changes only: messages sent while the space was
116
+ # closed, or before it bound, wait for a run started here.
117
+ idle = nu.List(snap(plane_live(engine))).len() == 0
118
+ waiting = nu.Bool(snap(ops.plane_state(engine, pending())))
119
+ caught_up = nu.IfDo(nu.And(idle, waiting), up_plane(engine))
120
+ return made >> kept >> settings.ensure() >> reaction >> caught_up
111
121
 
112
122
 
113
123
  def say(engine: nu.StrArg, text: nu.StrArg) -> nu.Nu:
@@ -150,7 +160,7 @@ def stop(engine: nu.StrArg) -> nu.Nu:
150
160
  when a call will not let go). What it said so far stays.
151
161
  """
152
162
  handled = Chat.cursor.set(Chat.inbox.len()) >> Chat.status.set(STOPPED)
153
- live = snap(nu.list(Space.kernel.planes_running[engine].runs))
163
+ live = snap(plane_live(engine))
154
164
  stopping = nu.ForEachDo(live, lambda run: ops.plane_stop(nu.Str(run)))
155
165
  return ops.atomic_state(ops.plane_state(engine, handled)) >> stopping
156
166
 
@@ -342,8 +352,9 @@ def said(page: nu.StrArg, at: nu.IntArg) -> nu.Nu:
342
352
  return text >> trace.set(title=_title(steps, s["done"])) >> nu.ForEachDo(steps, turn)
343
353
 
344
354
  moves = [Chat.inbox.on_change(), Chat.turns.on_change(), Chat.cursor.on_change()]
345
- return redraws(
346
- [ops.plane_state(engine, m) for m in moves], ops.plane_state(engine, _trace(at)), draw
355
+ changes = [ops.plane_state(engine, m) for m in moves]
356
+ return nu.Reconcile(
357
+ snap(nu.OnAny(*changes)), nu.let(snap(ops.plane_state(engine, _trace(at))), draw)
347
358
  )
348
359
 
349
360
 
@@ -414,8 +425,12 @@ def composer(page: nu.StrArg) -> nu.Nu:
414
425
  ensure(page)
415
426
  >> placed
416
427
  >> nu.ParallelAsync(
417
- redraws(on, ops.plane_state(engine, _shown()), draw, every=5.0),
418
- nu.ReactForever(actions.send.on_click(), nu.let(nu.Str(box).strip(), sent)),
419
- nu.ReactForever(actions.stop.on_click(), stop(engine)),
428
+ nu.Reconcile(
429
+ snap(nu.OnAny(*on)),
430
+ nu.let(snap(ops.plane_state(engine, _shown())), draw),
431
+ every=5.0,
432
+ ),
433
+ nu.ReactEvery(actions.send.on_click(), nu.let(nu.Str(box).strip(), sent)),
434
+ nu.ReactEvery(actions.stop.on_click(), stop(engine)),
420
435
  )
421
436
  )
@@ -164,7 +164,7 @@ def _record(at: nu.Int) -> nu.Nu:
164
164
  kept = nu.Dict.of(
165
165
  at=at,
166
166
  reply=Chat.reply.fallback(""),
167
- program=nu.str(Chat.program).fallback(""),
167
+ program=nu.str(Chat.program.fallback("")),
168
168
  kind=Chat.outcome.kind.fallback(""),
169
169
  observation=nu.str(told["content"]),
170
170
  )
@@ -23,7 +23,7 @@ import nuspace
23
23
  import nustd.kv
24
24
  import nustd.ui
25
25
  from nuspace import ops
26
- from nuspace.system.utils import redraws, snap
26
+ from nuspace.system.utils import snap
27
27
 
28
28
 
29
29
  if TYPE_CHECKING:
@@ -157,9 +157,10 @@ def out() -> nu.Nu:
157
157
  >> Config.key_env.set(nu.Str(form.key_env.input).strip())
158
158
  )
159
159
  slots = (Config.backend, Config.model, Config.endpoint, Config.key_env)
160
+ changes = [slot.on_change() for slot in slots]
160
161
  return form.save.set("Save") >> nu.ParallelAsync(
161
- redraws([slot.on_change() for slot in slots], _values(), show),
162
- nu.ReactForever(form.save.on_click(), ops.atomic_state(typed)),
162
+ nu.Reconcile(snap(nu.OnAny(*changes)), nu.let(snap(_values()), show)),
163
+ nu.ReactEvery(form.save.on_click(), ops.atomic_state(typed)),
163
164
  )
164
165
 
165
166
 
@@ -187,6 +187,6 @@ class ClaudeCode:
187
187
  elif isinstance(self.sid, str):
188
188
  held = nu.Frame(Thread, session, sid=self.sid)
189
189
  else:
190
- minted = nu.IfDo(self.sid.is_empty(), self.sid.set(nustd.cc.NewSession()))
190
+ minted = nu.IfDo(self.sid.is_null(), self.sid.set(nustd.cc.NewSession()))
191
191
  held = minted >> nu.Frame(Thread, session, sid=self.sid)
192
192
  return nu.With(nustd.cc.bind(Agent, **self.options), body=held)
File without changes
File without changes