Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
41b5577
fix micgroup getting overwritten issue
zfoong Apr 29, 2026
8d670b7
fix micgroup getting overwritten issue
zfoong Apr 29, 2026
72d6dfe
Merge branch 'V1.3.1' of https://github.com/CraftOS-dev/CraftBot into…
ahmad-ajmal Apr 29, 2026
386182b
feature/clear conversation and task function and buttons
zfoong Apr 29, 2026
6ff7ce4
Merge pull request #235 from CraftOS-dev/feature/clear-conversation-a…
zfoong Apr 29, 2026
781c7e3
refactor craftos_integrations
ahmad-ajmal Apr 30, 2026
f0e7546
optional integrations load
ahmad-ajmal Apr 30, 2026
e3863ee
oauth fix
ahmad-ajmal Apr 30, 2026
209a66f
oauth uses helpers
ahmad-ajmal Apr 30, 2026
5d48461
telegram connection fix
ahmad-ajmal Apr 30, 2026
980c383
import fix
ahmad-ajmal Apr 30, 2026
0f7c8bb
whatsapp web connection fix + icons
ahmad-ajmal Apr 30, 2026
b3ce8de
feature:skill creation/improved from completed task
zfoong May 1, 2026
f07de38
refactor:Move reserved skill list away from task page
zfoong May 2, 2026
b2c97ae
improve whatsapp UX
ahmad-ajmal May 4, 2026
d3ddd00
google workspace as separate services
ahmad-ajmal May 4, 2026
d3700a9
per integration config
ahmad-ajmal May 4, 2026
0167bdc
LINE Messageing API + Whatsapp fix + How to connect
ahmad-ajmal May 5, 2026
5ad3229
discord config
ahmad-ajmal May 5, 2026
d4dc8dd
Update AGENT.md
zfoong May 5, 2026
5f97ae7
Merge pull request #236 from CraftOS-dev/feature/skill-creation-from-…
zfoong May 6, 2026
608758c
Open router initiate implementation
zfoong May 7, 2026
02cfc0d
MiniMax & Moonshot is added.
korivi-CraftOS May 7, 2026
26b07e2
Lark (in-progress)
ahmad-ajmal May 7, 2026
94b5ec5
Update LLM call error display and improve chat pannel UI
zfoong May 8, 2026
a49846d
Fix chat panel scroll to botton button display logic
zfoong May 8, 2026
65583f6
lark instructions
ahmad-ajmal May 8, 2026
008e4fb
lark calendar and drive
ahmad-ajmal May 8, 2026
67b443c
LLM call error handling and display
zfoong May 9, 2026
4946ce4
Fix token limit is global issue
zfoong May 10, 2026
8c28d3b
OpenRouter integration - bugs Fix
korivi-CraftOS May 11, 2026
9f4ccc7
Merge pull request #239 from CraftOS-dev/feature/open-router
korivi-CraftOS May 11, 2026
6a9954b
OpenRouter handlers are added.
korivi-CraftOS May 11, 2026
8337ad4
Add coding agent skills
zfoong May 11, 2026
892d245
VLM model IDs are now set in model registry
korivi-CraftOS May 11, 2026
aa2edc9
Fix google gemini api deprecated warning
zfoong May 12, 2026
55ed9bd
Merge branch 'V1.3.1' of https://github.com/CraftOS-dev/CraftBot into…
zfoong May 12, 2026
401c8ea
OpenRouter bug fixes
korivi-CraftOS May 12, 2026
a2a2ee3
UI auto-routing and model preset changes are fixed.
korivi-CraftOS May 12, 2026
bd4df93
Issue #240 fixed
korivi-CraftOS May 12, 2026
70e37fb
Docker Issue Fixed
korivi-CraftOS May 12, 2026
11debe4
Merge branch 'V1.3.1' into refactor/craftos-integrations
ahmad-ajmal May 13, 2026
884bffc
readme update
ahmad-ajmal May 13, 2026
47a04a4
Merge pull request #253 from CraftOS-dev/refactor/craftos-integrations
ahmad-ajmal May 13, 2026
4d3d3d7
imrpovement:improve prompt and split google workspace action set
zfoong May 14, 2026
5f82618
whatsapp search fix
ahmad-ajmal May 14, 2026
067cfab
integration information
ahmad-ajmal May 14, 2026
db6e182
fix for add_github_labels and other csv_list requiring functions in g…
makiroll1125 May 15, 2026
411d6f6
fixed box-alignment width when running craftbot.py status based on cr…
makiroll1125 May 15, 2026
7794033
create end to end integration test
ahmad-ajmal May 15, 2026
a39d2d3
live whatsapp tests
ahmad-ajmal May 15, 2026
64d261e
2 way whatsapp tests
ahmad-ajmal May 15, 2026
b18cb8a
gmail tests
ahmad-ajmal May 15, 2026
aff13ea
fixed integration error
ahmad-ajmal May 15, 2026
b00a15d
move integrations
ahmad-ajmal May 15, 2026
cd83463
bug:fix silent error issue
zfoong May 16, 2026
1c14743
Merge branch 'V1.3.1' of https://github.com/CraftOS-dev/CraftBot into…
zfoong May 16, 2026
c2a23d4
bug:Fix LLM call bloat event stream
zfoong May 16, 2026
4b093d9
feature:show task session token usage
zfoong May 17, 2026
84b28e7
bug:fix routing is deterministic issue
zfoong May 17, 2026
98a898d
UI:todo list pretty display
zfoong May 17, 2026
782afbc
Fix#252: Deleted Living UI tabs do not disappear from tabs bar
ahmad-ajmal May 18, 2026
f249d50
Fix #251: CraftBot does not list aborted tasks as failed
ahmad-ajmal May 18, 2026
fa965ef
Fix #237: Data updated in Living UI not displayed visually
ahmad-ajmal May 18, 2026
7570704
integration usage md files
ahmad-ajmal May 18, 2026
42728f4
Merge pull request #257 from CraftOS-dev/bug/github-integration-csv-list
ahmad-ajmal May 18, 2026
66615f3
line integration name change
ahmad-ajmal May 18, 2026
25b8338
living ui marketplace redesign
ahmad-ajmal May 18, 2026
743dcaa
bug:fix skill not placed correctly by craftbot issue
zfoong May 18, 2026
1b56787
skills:add remotion skill
zfoong May 18, 2026
017caf6
fix startup warning
zfoong May 18, 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
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ app/config/settings.json
**/CONVERSATION_HISTORY.md
**/EVENT_UNPROCESSED.md
**/EVENT.md
**/TASK_HISTORY.md
agent_file_system/TASK_HISTORY.md
**/USER.md
**/onboarding_config.json
**/config.json
Expand Down
20 changes: 15 additions & 5 deletions agent_core/core/impl/action/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,13 +387,23 @@ async def execute_action(

logger.debug(f"Persisting final state for action {action.name}...")

# Update action count in state
state = get_state_or_none()
if state:
state.set_agent_property(
# Update action count on the per-task StateSession (per-task counter).
# Falls back to the global state provider when no session is registered
# (e.g. transient/conversation-mode actions before any task is created).
from agent_core.core.state.session import StateSession
session = StateSession.get_or_none(session_id) if session_id else None
if session is not None:
session.agent_properties.set_property(
"action_count",
state.get_agent_property("action_count", 0) + 1
session.agent_properties.get_property("action_count", 0) + 1,
)
else:
state = get_state_or_none()
if state:
state.set_agent_property(
"action_count",
state.get_agent_property("action_count", 0) + 1
)

# Call on_action_end hook if provided
if self._on_action_end:
Expand Down
82 changes: 74 additions & 8 deletions agent_core/core/impl/action/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,12 @@ async def select_action(
# Base conversation mode actions
base_actions = ["send_message", "task_start", "ignore"]

# Dynamically add messaging actions for connected platforms
# Dynamically add messaging actions for connected platforms.
# Curation (which actions match which integration) lives in the host —
# the package only reports which platforms are currently connected.
try:
from app.external_comms.integration_discovery import (
get_connected_messaging_platforms,
get_messaging_actions_for_platforms,
)
connected_platforms = get_connected_messaging_platforms()
messaging_actions = get_messaging_actions_for_platforms(connected_platforms)
conversation_mode_actions = base_actions + messaging_actions
from app.data.action.integrations._routing import get_messaging_actions_for_connected
conversation_mode_actions = base_actions + get_messaging_actions_for_connected()
except Exception as e:
logger.debug(f"[ACTION] Could not discover messaging actions: {e}")
conversation_mode_actions = base_actions
Expand All @@ -124,12 +121,31 @@ async def select_action(
"output_schema": act.output_schema
})

# Pull just-in-time guidance for any integrations the user named.
# No-ops to "" when nothing matches; never raises. See the helper
# in the host app — kept out of agent_core so the package stays
# integration-agnostic.
try:
from app.data.action.integrations._integration_essentials import (
get_essentials_for_message,
)
# TODO: Is keyword based deterministic search good enough?
integration_essentials = get_essentials_for_message(query)
logger.info(
f"[ACTION] integration essentials: "
f"{len(integration_essentials)} chars injected"
)
except Exception as e:
logger.debug(f"[ACTION] integration essentials lookup failed: {e}")
integration_essentials = ""

# Build the instruction prompt for the LLM
full_prompt = SELECT_ACTION_PROMPT.format(
event_stream=self.context_engine.get_event_stream(),
memory_context=self.context_engine.get_memory_context(query),
query=query,
action_candidates=self._format_candidates(action_candidates),
integration_essentials=integration_essentials,
)

max_format_retries = 3
Expand Down Expand Up @@ -219,13 +235,39 @@ async def select_action_in_task(
task_state = self.context_engine.get_task_state(session_id=session_id)
memory_context = self.context_engine.get_memory_context(query, session_id=session_id)
event_stream_content = self.context_engine.get_event_stream(session_id=session_id)

# Pull integration essentials the same way conversation-mode does
# (see select_action). Without this, the task-mode LLM loses sight
# of integration-specific shortcuts (e.g. WhatsApp's `to: "user"`
# self-send) once the agent enters task mode and starts asking the
# user for info the integration could look up itself.
# Match against both the current step's query and the task state so
# the platform name from the original user request still triggers a
# match even after the per-step query is generic ("Perform the next
# best action...").
try:
from app.data.action.integrations._integration_essentials import (
get_essentials_for_message,
)
integration_essentials = get_essentials_for_message(
f"{query}\n{task_state}"
)
logger.info(
f"[ACTION] task-mode integration essentials: "
f"{len(integration_essentials)} chars injected"
)
except Exception as e:
logger.debug(f"[ACTION] task-mode essentials lookup failed: {e}")
integration_essentials = ""

static_prompt = SELECT_ACTION_IN_TASK_PROMPT.format(
agent_state=self.context_engine.get_agent_state(session_id=session_id),
task_state=task_state,
memory_context=memory_context,
event_stream="", # Empty for static prompt
query=query,
action_candidates=self._format_candidates(action_candidates),
integration_essentials=integration_essentials,
)
full_prompt = SELECT_ACTION_IN_TASK_PROMPT.format(
agent_state=self.context_engine.get_agent_state(session_id=session_id),
Expand All @@ -234,6 +276,7 @@ async def select_action_in_task(
event_stream=event_stream_content,
query=query,
action_candidates=self._format_candidates(action_candidates),
integration_essentials=integration_essentials,
)

max_format_retries = 3
Expand Down Expand Up @@ -325,13 +368,35 @@ async def select_action_in_simple_task(
task_state = self.context_engine.get_task_state(session_id=session_id)
memory_context = self.context_engine.get_memory_context(query, session_id=session_id)
event_stream_content = self.context_engine.get_event_stream(session_id=session_id)

# Inject integration essentials so the simple-task LLM still sees
# integration-specific shortcuts (e.g. WhatsApp's `to: "user"`)
# even after the agent has left conversation mode. Match against
# the per-step query AND the task state so the original platform
# keyword still triggers a hit.
try:
from app.data.action.integrations._integration_essentials import (
get_essentials_for_message,
)
integration_essentials = get_essentials_for_message(
f"{query}\n{task_state}"
)
logger.info(
f"[ACTION] simple-task integration essentials: "
f"{len(integration_essentials)} chars injected"
)
except Exception as e:
logger.debug(f"[ACTION] simple-task essentials lookup failed: {e}")
integration_essentials = ""

static_prompt = SELECT_ACTION_IN_SIMPLE_TASK_PROMPT.format(
agent_state=self.context_engine.get_agent_state(session_id=session_id),
task_state=task_state,
memory_context=memory_context,
event_stream="", # Empty for static prompt
query=query,
action_candidates=self._format_candidates(action_candidates),
integration_essentials=integration_essentials,
)
full_prompt = SELECT_ACTION_IN_SIMPLE_TASK_PROMPT.format(
agent_state=self.context_engine.get_agent_state(session_id=session_id),
Expand All @@ -340,6 +405,7 @@ async def select_action_in_simple_task(
event_stream=event_stream_content,
query=query,
action_candidates=self._format_candidates(action_candidates),
integration_essentials=integration_essentials,
)

max_format_retries = 3
Expand Down
5 changes: 4 additions & 1 deletion agent_core/core/impl/context/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,14 @@ def create_system_environmental_context(self) -> str:
def create_system_file_system_context(self) -> str:
"""Create a system message block with agent file system context."""
try:
from app.config import AGENT_FILE_SYSTEM_PATH
from app.config import AGENT_FILE_SYSTEM_PATH, PROJECT_ROOT
skills_path = PROJECT_ROOT / "skills"
except ImportError:
AGENT_FILE_SYSTEM_PATH = "."
skills_path = "./skills"
return AGENT_FILE_SYSTEM_CONTEXT_PROMPT.format(
agent_file_system_path=AGENT_FILE_SYSTEM_PATH,
skills_path=skills_path,
)

def create_system_user_profile(self) -> str:
Expand Down
Loading