Skip to content

Parsar: Core saved Agents and Templates, unified library, and Feishu delivery fixes - #905

Merged
SaladDay merged 21 commits into
mainfrom
parsar-core-agents
Oct 29, 2026
Merged

SaladDay merged 21 commits into
mainfrom
parsar-core-agents

Conversation

@SaladDay

@SaladDay SaladDay commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Agents and environment templates are saved as Core Agents and Environment Templates; Sessions reference them and keep their creation-time configuration for recovery. Capabilities are modular per kind, and only current dependencies (bot bindings, an Agent using a template, model or capability) block deletion; history never does.
  • Resource Library: one capability list with enabled-Agent counts and credential requirements, one "new capability" entry, write-only secrets, and per-Agent credential choices. A bound Feishu bot's identity reaches every conversation automatically.
  • Harness options are generated from the Harness declarations (make generate-harness-catalog).
  • Feishu: one timeline card per turn with every step kept in the card and no links to the Web; steers join the running turn; one private-chat thread per sender with /clear (formatted commands included); files the reply names are sent as replies to the message; missing-scope cards link to applying for the scopes the reply names; each message carries its source IDs; QR-created bots request the organization's review-free scopes and take their Feishu name; bots delete at once.
  • Attachments and Web uploads go through Core's Files API, up to 50 MiB.
  • Merges main's uncertain-submission confirmation (fix: stabilize sandbox suspension and uncertain Parsar submissions #881) with steering.

Test plan

Generated with Devin


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

SaladDay and others added 21 commits October 25, 2026 21:53
The card had lost its colored status header, and its process was split
into separate thinking, commentary and tool-call sections, so following
what the Agent did meant opening three panels. Cards again carry a colored
header, and the process is one chronological timeline: commentary as plain
text, thinking folded behind its first sentence, and each tool call showing
what ran with its duration, failure or 进行中 while its result folds away.
A running card shows the latest four steps and folds the earlier ones; a
finished card puts the answer first and folds the whole process; a failed
card shows the failed step under its cause. The oldest steps leave the card
first to stay within Feishu's size limit.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Only commentary now stays open in the card timeline: consecutive tool
calls fold into one row with their total time, failures or 进行中, and
each call folds again behind its command. Size fitting reaches into a
folded row when that row alone is too large.

Feishu commands are /clear, which stops running work and makes the next
message start a new conversation (in a private chat or in the same group
topic), /stop for the current task, /answer and /help. They replace /new,
/reset and /cancel.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The running card's status line took the first body row. The header now
carries what is happening and how many steps have run, so the timeline
starts the body. Earlier steps and a finished card's process sit in a
tinted, rounded block, and a divider separates earlier steps from the
latest ones.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Feishu treats any Markdown image as an image key and rejects the whole
card. Thinking that quoted the authorization QR image made every edit of
that Turn's card fail, silently, so the card stayed 处理中. When the next
message arrived, the older Turn's result took the new message's progress
card (with its content cut by the new display boundary), and the new
Turn's answer edited the topic's first card instead.

Markdown images now become text in every card row. Each Turn's result goes
to the progress card of the input it answers, found through the Turn
ledger; an older Turn never takes a newer message's card, and there is no
fallback to the conversation's first card. An older Turn shows all of its
items. Observation failures are logged.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The 测试 and 试运行 rows added small status text such as "可用 · 首次回复
8 秒" beside the button. The button now shows the result itself; only a
failure adds text, since it says what to fix. Attachment sizes no longer
add small grey text either.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Parsar kept its Agents and environment templates in SQLite and inlined
all of their configuration into every Session request, so the example
never showed the Agents API's own Agent and Environment Template
resources and kept a second home for that configuration.

Each Agent is now a saved Core Agent (model, instructions, tools, Harness)
and each environment template a Core Environment Template (packages,
setup, variables, files). Parsar writes them on save, rolls a save back
when Core rejects it, deletes them with the record, rewrites them when
anything they bind changes, and recreates them on next use after a Project
move. A Session references both and adds only the bot variables, the
Agent's Skills, Plugins and knowledge, and attachments. The browser proxy
no longer exposes /v1/agents.

Every capability kind (Skills, MCP, prompts, knowledge, Plugins) is one
definition in capability-kinds.mjs that resolves an Agent's bindings and
says where each goes, replacing the per-kind code in Session creation.

Only live configuration blocks deletion: an Agent that binds an item or
uses a template or model, or a bot bound to an Agent. Conversations keep
their snapshot and history. A Skill an Agent binds is not deleted.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ry conversation

The library listed each capability kind on its own page, credentials were
bound to MCP servers for every Agent alike, and a bot's identity reached a
conversation only when its environment template mapped the bot's fields
to variables, which templates easily missed: an Agent with a bound bot then
ran without identity and tried to register a new app.

资源库 now has 能力, 模型 and 凭据. 能力 lists every Skill, MCP, Plugin,
instruction fragment and knowledge item with its version, enabled Agents
and the credentials it needs, and 新建能力 adds any kind. Skills, Plugins
and environment templates declare the variables they need; each Agent
chooses a secret (凭据 → 密钥, write-only) for each, and a Vault credential
for each MCP marked as needing one. An Agent cannot be saved with a
credential missing, and choices nothing needs are dropped.

A bound bot's identity reaches every conversation of its Agent as
FEISHU_APP_ID, FEISHU_APP_SECRET and FEISHU_BRAND; only the bot supplies
these names. Declaring them marks a need for a bot. The template mapping
and its editor are removed. A bot takes the name its app has in Feishu
when it connects.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Core folds a message sent while a Turn runs into that Turn, but Parsar's
ledger recorded every message as a Turn of its own. 运行 then showed two
running rows for one task, and Feishu opened a second progress card while
the first one stopped updating.

A message that arrives while the conversation's Turn is still running in
Core is now recorded on that Turn and resent with it if the Turn is
retried. Feishu keeps the running Turn's card instead of opening another.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
A bot created by scanning lacked the "read all group messages" scope, so
it never received topic replies that did not mention it. The QR code now
carries the official SDKs' addons parameter, so the confirmation page after
scanning requests im:message.group_msg on top of the default template, and
pre-fills the app name entered in Parsar.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Parsar kept its own copy of each Harness's model protocol and execution
options and chose behavior by Harness name, and the copy had already
drifted: Codex lacked the fast service tier and Claude Code's auto
reasoning summary was rejected. make generate-harness-catalog now projects
the declared protocols, execution options, image input and required HTTP
MCP support into example/parsar/shared/harness-catalog.mjs, and Parsar's
image and MCP checks read those capabilities instead of the Harness name.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…nfiguration

Main confirms a Web message whose send timed out with the same idempotency
key before attributing a Turn to it. That now works with steering: only a
send that succeeds right away can join the running Turn at once; a
confirmed uncertain message joins it when the monitor sees it landed in
that Turn, and otherwise keeps a Turn of its own.

A conversation referenced its saved Core Agent and Template, which edits
update in place, so replacing a failed Environment could pick up a newer
configuration. Each conversation now also keeps its creation-time Agent and
Template inline until its first output, and a replacement Session is
created from that copy.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…sing scopes

A bot created by scanning had only the default template's scopes, so an
Agent working with Base or Calendar failed on its first call and its users
had to find and apply for each scope. The QR code now also requests
reading and writing Base, Calendar, Docs, Drive, Sheets, Wiki and Tasks and
basic contact information.

When the Agent's tools report scopes the bot's app lacks, the card now says
需要开通权限, lists them and links to the developer console's apply page,
with the Agent's explanation folded below, instead of a long reply.

Skills keyed to Feishu messages could not see which message they were
answering and treated Feishu input as Web input. Each Feishu message now
reaches the Agent after a line naming its message_id, chat_id, chat type and
sender; Parsar's views hide that line.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
A bolded /clear from Feishu's rich-text box did not count as a command, so
it started a conversation the Agent answered with a self-check. Commands
now count with their surrounding formatting removed.

Every file a turn wrote under ./outputs was posted to the chat as a reply
to the conversation's first message, including evidence and intermediate
files. Feishu now sends only the files the Agent's reply names, as replies
to the message the turn answers; all files stay in the Web conversation.

The "通常约 N 秒" hint is gone from Feishu cards, the conversation page and
运行; the usual time still decides when a turn reads as slow.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
A private chat got a new thread on every /clear, and later messages found
the sender's first thread rather than the newest, so a /clear could clear
one thread while the next message continued an older conversation. A
private chat now keeps one thread per sender, and /clear starts the next
conversation in it.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
A long turn dropped its oldest steps from the card and said "更早的 N 步见
网页对话", and a few Feishu replies told people to check the Web. Every step
now stays in the card: the oldest first lose their tool output, then
shrink to one line, and only a turn with hundreds of steps summarizes its
oldest ones in one line. Feishu replies no longer mention the Web.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Deleting a bot required stopping it first and refused while any message
was still queued for it, so a stuck delivery made a bot impossible to
delete. Deleting now stops the bot and drops what it had not delivered;
conversations and delivered messages stay.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The QR code requested 48 hand-picked scopes, a dozen of which need review
in the organization: calendar event, Drive and task write scopes. It now
requests 137 useful app-identity scopes from the organization's list of
scopes granted without review, so a new bot works with messages, Base,
Calendar, Docs, Sheets, Slides, Wiki, Tasks and meetings at once, and
leaves scopes that need review for when an Agent truly needs them. The QR
image grows to 640 pixels for the longer address.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
A scanned bot was named "Parsar", the name Parsar preset on the
confirmation page, and an added app showed its App ID, until the bot
first connected. Parsar no longer presets a name, so the app is named on
the confirmation page, and it reads the app's Feishu name with the app's
own credentials as soon as the bot is created or added.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The monitor wrote back a copy of a Turn it read before its Core calls, so
a message that joined the Turn meanwhile was lost, and Feishu then gave
that message a progress card of its own that never finished. The monitor
now keeps steers recorded meanwhile, and a Feishu message sent while Core
runs a Turn keeps that Turn's card.

The missing-scope card replaced the Agent's reply with every scope any
probe had hit, so a Base collaborator problem showed Drive scopes. The
reply now stays the card's body, and only scopes it names get an apply
link. Folded panels share one block style so they line up.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Feishu attachments and Web uploads were written into the workspace inline,
which Core caps at 5 MiB, so most slide decks were refused. They now go to
Core's Files API first and reach the workspace by File ID, which Core takes
up to 50 MiB; a Feishu message keeps only the File ID across retries.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Main added network access to Parsar's environment templates by mapping it
into the inline Session environment, which this branch replaced with saved
Core Environment Templates. The template's network now goes to the saved
Template; it is sent as null when enabled, because an update keeps an
omitted field and would otherwise leave a removed restriction in place.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@SaladDay
SaladDay marked this pull request as ready for review October 29, 2026 05:40
@SaladDay
SaladDay merged commit 325bc25 into main Oct 29, 2026
25 checks passed
@SaladDay
SaladDay deleted the parsar-core-agents branch October 29, 2026 05:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant