Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
900420e
Changed AI enhance reasoning to stick to the chosen language unless s…
RooberSmoth Aug 10, 2026
5e8626a
If the input is empty, stop enhancing and reset to false state.
RooberSmoth Aug 10, 2026
ddd9693
Updated chat.tsx as i committed the wrong version.
RooberSmoth Aug 10, 2026
47dc53c
Fix issue #416
Aug 10, 2026
05849bf
Added loading spinner to + button for visual communication.
RooberSmoth Aug 10, 2026
b756d1e
Disabled send and dictate button, added 'no entry' thing when hoverin…
RooberSmoth Aug 10, 2026
cb80a08
splash page loading animation
Aug 10, 2026
aef2fd7
Added 30s timeout - needs testing?
RooberSmoth Aug 10, 2026
bf92aa0
Merge branch 'dev' into V1.4.2
ahmad-ajmal Aug 10, 2026
f292f47
make chat input disabled
Aug 10, 2026
a0e5dba
Merge pull request #415 from CraftOS-dev/ai-enhance-fix
zfoong Aug 10, 2026
5b6d065
Remove outdated sections in living UI setting page
Aug 10, 2026
57acb8c
introduce graph into the memory system
Aug 13, 2026
f67d641
fix coloring issue on nodes
Aug 13, 2026
e8f1dfb
remove pending visualization
Aug 13, 2026
83cb33c
Update graph UI and update relevent memories preview logic
Aug 13, 2026
47df7bb
entity in memory graph are stored and retrieved as embedding
Aug 13, 2026
e52578c
Advertisement Widget
Aima-Ajmal Aug 14, 2026
6fc8abf
Update memory setting page and added configurable memory processing c…
Aug 14, 2026
b62dcca
improve welcome widget
Aug 14, 2026
6c6562c
minor update to the token usage widget
Aug 14, 2026
6f4f3b3
Merge pull request #420 from CraftOS-dev/feature/advertisement-widget
zfoong Aug 14, 2026
3b3b58d
Code clean up and refactor
Aug 14, 2026
c4090a9
refactor memory system and consolidate magic numbers into a file
Aug 14, 2026
64b9c82
fix entities and connection pipeline
Aug 14, 2026
e1195d9
bug:invoking skill and command cause new chat session to stuck
Aug 15, 2026
2565ae3
Added new guide tour with driver js
Aug 16, 2026
208bd91
update guide text
Aug 16, 2026
0ffde11
Added more providers and provider refactor
Aug 18, 2026
0f60cd8
Merge pull request #426 from CraftOS-dev/feature/guided-tour
zfoong Aug 20, 2026
973e120
fix: merge reset-agent chat options and refresh the session list
false200 Aug 20, 2026
120d132
Merge branch 'V1.4.2' into fix/reset-agent-chats-option
false200 Aug 20, 2026
94d906b
feat: agent questions with suggested responses (pinned question box)
ahmad-ajmal Aug 20, 2026
7dfd1cb
bug:fix run shell mangle issue on windows
Aug 21, 2026
151de9c
Fix message disappearing issue
Aug 21, 2026
19fb572
fix event stream summarization failed and chat session UI scrolling i…
Aug 21, 2026
a3a3010
bug:fix reset agent require refresh to take effect
Aug 21, 2026
dfce2f8
Merge pull request #430 from CraftOS-dev/feature/agent-suggested-resp…
zfoong Aug 21, 2026
b13ce93
fix: unify Living UI dev/live lifecycle to stop live pb_data wipes (#…
ahmad-ajmal Aug 21, 2026
baa6549
Merge branch 'V1.4.2' into fix/reset-agent-chats-option
CraftOS-dev Aug 21, 2026
df35bed
Merge pull request #429 from false200/fix/reset-agent-chats-option
CraftOS-dev Aug 21, 2026
b0c0685
fix and improve reset agent feature from merge
Aug 22, 2026
05625fa
bug:schedule task list action parameter bug
Aug 22, 2026
bb409d8
Merge branch 'V1.4.2' into feature/memory_system_improvement
zfoong Aug 23, 2026
29b2d2f
Merge pull request #421 from CraftOS-dev/feature/memory_system_improv…
zfoong Aug 23, 2026
307849e
update intsaller check in run script
Aug 23, 2026
e25d88f
fix multiple file indexing issue
Aug 24, 2026
7222e69
Feature/multiaccount integrations (#419)
ahmad-ajmal Aug 24, 2026
c3da74c
fix: import external apps
ahmad-ajmal Aug 24, 2026
28b2038
Document + version fix
ahmad-ajmal Aug 24, 2026
21149f7
memory entity connection processed by deterministic pipeline for now
Aug 24, 2026
d9caded
Merge branch 'V1.4.2' of https://github.com/craftos-dev/craftbot into…
Aug 24, 2026
5a039b4
Add guided tour for memory panel
Aug 25, 2026
54e05fc
Update multiple options UI
Aug 25, 2026
e2486c3
fix: update node install
ahmad-ajmal Aug 25, 2026
a5e0120
fix: normalise python
ahmad-ajmal Aug 25, 2026
16da130
fix: windows dll issue
ahmad-ajmal Aug 25, 2026
aeab106
feat: scoped walk-verify - the verifier decides what to re-test
ahmad-ajmal Aug 26, 2026
0f56ed2
feat: make Living UI marketplace branch configurable
ahmad-ajmal Aug 26, 2026
e4c963f
refactor: Cleanup legacy integrations code
ahmad-ajmal Aug 26, 2026
17cfe11
hard onboarding step upgrad
Aug 26, 2026
15c6d6c
Overwrite ENTITIES.md with clean data
Aug 26, 2026
fd30f56
Merge branch 'V1.4.2' of https://github.com/craftos-dev/craftbot into…
Aug 26, 2026
5349ff7
Fix local LLM provider dropdown, server url input, and test connectio…
Aug 27, 2026
5ca49fc
Merge remote-tracking branch 'origin/V1.4.2' into improvement/llm-pro…
Aug 27, 2026
7cde06a
Merge pull request #423 from CraftOS-dev/improvement/llm-providers-up…
zfoong Aug 27, 2026
f2229a7
Fix question UI and updated AGENT.md to fit the latest update
Aug 27, 2026
c54e2f6
merging
Aug 27, 2026
2da01b6
Give agent more context of living UI, memory and integration
Aug 27, 2026
eeb1814
fix provider issue with openai and gemini
Aug 28, 2026
1df3ce0
fix: version name + event stream summarization
ahmad-ajmal Aug 28, 2026
938d55d
fix: tunnel fix for pocketbase
ahmad-ajmal Aug 28, 2026
c3ba000
fix: marketplace name normalization
ahmad-ajmal Aug 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,6 @@ agent_file_system/ACTIONS.md
agent_bundle/
**/.craftbot/
app/data/.file_index/
.playwright-mcp
.playwright-mcp
# Sidecar Node runtime (install.py downloads it when the system Node is too old for Living UI)
runtime/
9 changes: 9 additions & 0 deletions agent_core/core/event_stream/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ class Event:
uses it to keep the run's "Working…" indicator up across the
bubble instead of treating every agent bubble as a run-ending
reply. None/False for final replies and non-chat events.
question: For AGENT_MESSAGE events only: set when the message is a
question to the user with suggested responses (send_message with
suggested_responses). Shape:
``{"options": ["Yes", "No"], "allow_free_text": true}``. The UI
renders it as answer chips plus a pinned question box above the
chat composer. None for ordinary messages.
"""

message: str
Expand All @@ -157,6 +163,7 @@ class Event:
action_output: Optional[Dict[str, Any]] = None
platform: Optional[str] = None
continue_work: Optional[bool] = None
question: Optional[Dict[str, Any]] = None

def display_text(self) -> Optional[str]:
"""
Expand Down Expand Up @@ -189,6 +196,7 @@ def to_dict(self) -> Dict[str, Any]:
"action_output": self.action_output,
"platform": self.platform,
"continue_work": self.continue_work,
"question": self.question,
}

@classmethod
Expand Down Expand Up @@ -228,6 +236,7 @@ def from_dict(cls, data: Dict[str, Any]) -> "Event":
action_output=data.get("action_output"),
platform=data.get("platform"),
continue_work=data.get("continue_work"),
question=data.get("question"),
)

@property
Expand Down
41 changes: 41 additions & 0 deletions agent_core/core/impl/action/context.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""Execution-scoped context for in-process actions.

``current_input_data`` holds the full ``input_data`` dict of the action
currently executing in this context. It exists so cross-cutting helpers
deep inside an action's call tree (e.g. multi-account routing reading the
``account`` hint) can see routing keys without threading them through
every action function signature.

Scope rules:
- Set only by the internal executors (``_atomic_action_internal*``),
reset in a ``finally`` — never leaks across actions.
- Sync actions run in a thread pool where the caller's context does NOT
propagate, so the executor wraps the call and sets the var inside the
worker thread (see ``run_with_input_context``).
- Sandboxed (subprocess) actions cannot see it at all — helpers must
treat a ``None`` value as "no context available".
"""

from __future__ import annotations

from contextvars import ContextVar
from typing import Any, Callable, Dict, Optional

current_input_data: ContextVar[Optional[Dict[str, Any]]] = ContextVar(
"current_input_data", default=None
)


def run_with_input_context(
function_to_call: Callable[[dict], dict], input_data: dict
) -> dict:
"""Call a sync action with ``current_input_data`` set for its duration.

Used as the thread-pool target: the worker thread has its own context,
so the var must be set (and reset) inside the thread, not the caller.
"""
token = current_input_data.set(input_data)
try:
return function_to_call(input_data)
finally:
current_input_data.reset(token)
23 changes: 19 additions & 4 deletions agent_core/core/impl/action/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,9 @@ def _atomic_action_internal(
"The action_code string did not define a callable Python function."
)

execution_result = function_to_call(input_data)
from agent_core.core.impl.action.context import run_with_input_context

execution_result = run_with_input_context(function_to_call, input_data)
return execution_result

except Exception as e:
Expand Down Expand Up @@ -618,16 +620,29 @@ async def _atomic_action_internal_async(
"The action_code string did not define a callable Python function."
)

from agent_core.core.impl.action.context import (
current_input_data,
run_with_input_context,
)

# Check if the function is async (coroutine function)
if inspect.iscoroutinefunction(function_to_call):
logger.debug(f"[ASYNC] Action '{action_name}' is async, awaiting directly")
execution_result = await function_to_call(input_data)
ctx_token = current_input_data.set(input_data)
try:
execution_result = await function_to_call(input_data)
finally:
current_input_data.reset(ctx_token)
else:
# Sync function - run in thread pool to avoid blocking
# Sync function - run in thread pool to avoid blocking. The
# worker thread doesn't inherit this context, so the wrapper
# sets current_input_data inside the thread.
logger.debug(
f"[SYNC] Action '{action_name}' is sync, running in thread pool"
)
thread_future = THREAD_POOL.submit(function_to_call, input_data)
thread_future = THREAD_POOL.submit(
run_with_input_context, function_to_call, input_data
)
try:
execution_result = await asyncio.wrap_future(thread_future)
except asyncio.CancelledError:
Expand Down
42 changes: 38 additions & 4 deletions agent_core/core/impl/action/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,43 @@ async def _compat_wait_for(fut, timeout):

nest_asyncio.apply()

# ============================================================================
# Second half of the nest_asyncio/3.14 shim: heal asyncio.current_task().
# nest_asyncio forces the PURE-PYTHON asyncio.Task class, whose tasks
# register in the Python-side registry (asyncio.tasks._py_current_task) —
# but asyncio.current_task stays bound to the C-accelerated registry, so it
# returns None inside EVERY task, on EVERY loop, process-wide. Everything
# built on `async with asyncio.timeout(...)` then dies with "Timeout
# (context manager) should be used inside a task" — most visibly the entire
# aiohttp CLIENT (every request enters a timeout context), which is what
# broke the external A2App adapter self-check on 2026-08-24 while the
# aiohttp SERVER (no timeout context on the request path) kept working.
# Rebinding current_task to the Python registry fixes timeout/aiohttp under
# both plain awaits and nested re-entry (verified on 3.14.7 + aiohttp
# 3.14.3). The wait_for replacement above stays: its explicit
# cancellation-wait semantics are load-bearing for force-stop (PR #410).
try:
import _asyncio as _compat_c_asyncio

if asyncio.Task is not getattr(_compat_c_asyncio, "Task", None) and hasattr(
asyncio.tasks, "_py_current_task"
):
asyncio.current_task = asyncio.tasks._py_current_task
asyncio.tasks.current_task = asyncio.tasks._py_current_task
try:
_compat_sys.stderr.write(
"[compat-shim] asyncio.current_task routed to the Python "
"task registry (action/manager)\n"
)
_compat_sys.stderr.flush()
except Exception:
pass
except Exception as _compat_ct_exc:
logger.warning(
f"[compat-shim] current_task rebinding skipped: {_compat_ct_exc!r}"
)
# ============================================================================


def _to_pretty_json(value: Any) -> str:
"""Serialize a value to pretty-printed JSON for readable logs and event streams."""
Expand Down Expand Up @@ -247,10 +284,7 @@ async def execute_action(
# re-execute work the ledger shows as already completed (or as
# interrupted mid-flight, where the effect may have happened).
idem_key = None
# if getattr(action, "irreversible", False) and self._idempotency_guard:

# TODO: Temporary turning idempotency guard off.
if 1 == 0:
if getattr(action, "irreversible", False) and self._idempotency_guard:
try:
decision = self._idempotency_guard.begin(
action.name, input_data, session_id
Expand Down
6 changes: 4 additions & 2 deletions agent_core/core/impl/context/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -457,8 +457,10 @@ def get_session_state(self, session_id: Optional[str] = None) -> str:
f"Session ID: {session.id}",
f"Session Type: {session.type}",
]
if session.title:
lines.append(f"Session Title: {session.title}")
# Session Title is intentionally omitted: it is auto-generated/
# updated a turn or two into a session, and this block sits in the
# cacheable prefix (ahead of the event stream), so a mutating title
# would break the KV-cache prefix every time it changed.
if getattr(session, "living_ui_project_id", None):
lines.append(f"Living UI Project: {session.living_ui_project_id}")
lines.append(f"Loaded Action Sets: {['core'] + list(session.action_sets)}")
Expand Down
Loading
Loading