Commit Graph
29 Commits
Author SHA1 Message Date
weichen e86e74bc36 Preserve streamed tool delta identity
ci / docker-checkout-hostgateway (pull_request) Successful in 1s
ci / vet-and-test (pull_request) Successful in 52s
Why: Backend emitted tool deltas from a separate goroutine, racing with serialized run events and occasionally losing a UI delta.

Evidence: Backend race detector reproduced concurrent event writes; Agent-Native identity test RED→GREEN; full vet and tests pass.

Impact: runtime tool delta events now carry provider slot and call ID for single-owner downstream projection.

Refs: runtime/loop.go; runtime/event_vocabulary_test.go
2026-10-14 02:22:34 +00:00
weichen 94afd71f00 Reject incomplete streamed tool calls
ci / docker-checkout-hostgateway (pull_request) Successful in 0s
ci / vet-and-test (pull_request) Successful in 51s
Why: a model tool finish could execute partial JSON or an unterminated SSE stream, while post-Usage errors could lose their charge.

Evidence: missing-DONE, malformed-JSON, identity, non-object and post-Usage RED→GREEN tests; GOWORK=off go vet ./... and go test -count=1 ./... passed.

Impact: invalid tool terminals fail without execution or automatic retry and retain returned Usage; valid text and multi-part tool streams keep working.

Refs: runtime/llm/sse.go; runtime/loop.go
2026-10-14 02:09:44 +00:00
weichen 7f60baeaf8 Run serial-flagged tool calls in order while others fan out
ci / vet-and-test (pull_request) Successful in 54s
ci / docker-checkout-hostgateway (pull_request) Successful in 1s
Why: Mutual exclusion alone does not preserve order. With parallel
execution the host cannot keep order-sensitive tools (card streaming
begin/append/commit, plan updates) correct by locking a mutex, because
whichever goroutine grabs the lock first is not necessarily the first
declared call - a real failure observed in the backend card-stream test.

Evidence: go test ./... green; TestLoopSerialToolsKeepOrder asserts the
serial calls execute in declaration order (s1->s2->s3) while parallel
calls still fan out.

Impact: New Config.SerialTools set. In parallel mode, matching calls run
sequentially on the caller goroutine in model-declared order; others
stay concurrent. Empty set keeps the previous all-parallel behavior;
sequential mode is untouched.

Refs: Dev task feature/agent-e1-parallel-fixes (F5).
2026-10-10 08:58:31 +00:00
weichen a5da18b710 Inject the active tool call into the Execute context
ci / vet-and-test (pull_request) Successful in 50s
ci / docker-checkout-hostgateway (pull_request) Successful in 1s
Why: With parallel tool execution the host-side tool wrapper can no
longer infer which invocation it is serving from a single in-flight
slot; tools need the call identity (ID/name/arguments) to pair process
state and per-call bookkeeping. Context injection keeps the tools
registry signature unchanged.

Evidence: go test ./... green; TestLoopToolSeesOwnCallInContext runs
two parallel calls and asserts each reads its own ID from ctx.

Impact: Additive WithToolCall/ToolCallFromContext helpers; runOne now
wraps the ctx before Execute. Callers that never inject keep ok=false
and are unaffected.

Refs: Dev task feature/agent-e1-parallel-fixes (F5 parallel wiring).
2026-10-10 08:48:26 +00:00
weichen 1f25049492 Carry tool CallID in loop events and add reasoning_split to the chat client
ci / vet-and-test (pull_request) Successful in 50s
ci / docker-checkout-hostgateway (pull_request) Successful in 1s
Why: Parallel tool execution makes same-turn tool events interleave, so
consumers can no longer pair starts and ends by order; the kernel Event
needs the call ID. MiniMax interleaved-thinking models stream their
reasoning inside content <think> blocks unless the OpenAI-compatible
request opts in with reasoning_split=true, which forces reasoning into
the dedicated reasoning_content field the SSE layer already captures.

Evidence: go test ./... green; new tests TestLoopToolEventsCarryCallID
and TestOpenAIChatBodyReasoningSplit pin both behaviors (regression
anchors for the backend parallel-work change).

Impact: Additive Event.CallID (empty for non-tool events; existing
consumers unaffected) and an opt-in Client.ReasoningSplit flag that only
adds a request field when set. No default behavior change.

Refs: Agent-System-Dev proposal 2026-10-10-agent-delegation-routing-sandbox.md
(F2/F5), Dev task feature/agent-e1-parallel-fixes.
2026-10-10 08:33:53 +00:00
weichen 28e237f646 Carry cache tokens on message_end events (N3 WP6 follow-up)
ci / vet-and-test (pull_request) Successful in 50s
ci / docker-checkout-hostgateway (pull_request) Successful in 1s
Why: hosts accumulating per message_end could not see cache hits; the
fields now ride the same event as the per-request totals.
Evidence: GOWORK=off go test green.
Impact: additive event fields.
Refs: Agent-Native#35
2026-10-07 17:03:10 +00:00
weichen 87ff3946df Split last-request/cache usage, emit terminal usage, and retry stream errors by default (N3 WP6)
ci / vet-and-test (pull_request) Successful in 49s
ci / docker-checkout-hostgateway (pull_request) Successful in 1s
Why: cache tokens were parsed but never accumulated, the usage event
carried only cumulative totals and was skipped on terminal paths
(audit N20 residual), and stream retry was host-opt-in so subagents,
the verifier, and squad runs were never retried.
Evidence: GOWORK=off go vet + go test -count=1 ./... green;
TestUsageEventSplitsLastAndCache (event carries Last*/cache),
TestUsageAccumulatesCacheTokens, TestBudgetStopEmitsTerminalUsage,
TestDefaultRetryAttemptsTwo (0 value = 2 retries with
auto_retry_start events), TestNegativeRetryAttemptsDisables (negative
= off), TestRetryNeverDuplicatesForwardedDeltas (the only-before-first-delta
invariant holds under the library default).
Impact: usage events now carry Last* and cache fields and are emitted
on budget/error terminal paths too; Config.RetryAttempts defaults to
2 (negative disables) so every host gets the existing retry semantics
without wrapping; default (unset) host wrappers should be retired to
avoid double retries.
Refs: Agent-System-Documents#43 (N3 plan WP6), audit N20
2026-10-07 16:31:21 +00:00
weichen bdb45c3c2c Add the memory port with loop recall injection and the memory_write tool (N3 WP5)
ci / vet-and-test (pull_request) Successful in 49s
ci / docker-checkout-hostgateway (pull_request) Successful in 1s
Why: the completion doc assigns the Memory port to the library; today
memory recall is a product-side interface assertion with no library
surface, AgentSpec.MemoryScope has no consumer, and the model has no
write-back path.
Evidence: GOWORK=off go vet + go test -count=1 ./... green;
TestLoopInjectsMemoryAndRegistersWrite (recall block lands after the
system section, memory_write executes through the loop),
TestEmptyRecallInjectsNothing (empty recall changes nothing),
TestBlockRenderOrderingAndCaps (deterministic order, expiry/empty
pruning), TestWriteToolValidation (fail-closed scope/type/content).
Impact: new opt-in Config.Memory/MemoryScope; nil port keeps behavior
byte-identical; injection is request-scoped (never persisted, never
accumulates) and deterministic ([记忆] text shape preserved for the
product migration).
Refs: Agent-System-Documents#43 (N3 plan WP5)
2026-10-07 16:05:36 +00:00
weichen fc0558fc93 Align spans with the OTel GenAI convention (N3 WP4)
ci / vet-and-test (pull_request) Successful in 51s
ci / docker-checkout-hostgateway (pull_request) Successful in 1s
Why: acceptance clause 3 requires span names and attributes to follow
the convention; today names were bare words with two ad-hoc attribute
keys, and every span got a fresh random trace with no parentage.
Evidence: GOWORK=off go vet + go test -count=1 ./... green;
TestSpanNamesFollowGenAIConvention (name suffixes, gen_ai.* key enum,
intValue usage, service.name resource, prompt/reserved-key exclusion),
TestLoopSpansFollowGenAIConvention (invoke_agent root with shared
trace, chat/execute_tool children with parent links, usage attrs on
chat spans); the pre-existing prompt-body denylist test passes
unchanged.
Impact: span names become invoke_agent <agent> / chat <model> /
execute_tool <tool>; attributes move to gen_ai.* with usage as
intValue; one Run shares one trace with invoke_agent as root. New
Config.AgentName/ProviderName (documented defaults keep old hosts
meaningful); telemetry StartFunc gains WithServiceName/WithEndpoint
options (defaults preserve current behavior).
Refs: Agent-System-Documents#43 (N3 plan WP4)
2026-10-07 15:36:35 +00:00
weichen e2be33f008 Add JournalOnly sessions and persist one-time history seeds (N3 WP2)
ci / vet-and-test (pull_request) Successful in 50s
ci / docker-checkout-hostgateway (pull_request) Successful in 0s
Why: the product conversation path needs the intent journal and
recovery pairing, but making the transcript the authoritative context
would freeze the assembled system prefix (memory/plans/injections go
stale). JournalOnly keeps the session as journal-only: recovery runs
against it, the context always comes from History, and the recovered
outcomes are injected as a system note. Separately, the one-time
History seed was memory-only and silently lost from the second run on
(authority mode); it is now persisted except in JournalOnly mode.
Evidence: GOWORK=off go vet + go test -count=1 ./... green;
TestJournalOnlyRecoversWithoutTranscriptAuthority (journal gets the
replayed pair exactly once, history never enters the journal, the
recovery note precedes the new user message, seeds stay out);
persistedProjection honors JournalOnly; all pre-existing durable and
harness tests pass unchanged (default semantics untouched).
Impact: new opt-in Config.JournalOnly; default (false) behavior is
byte-identical.
Refs: Agent-System-Documents#43 (N3 plan WP2)
2026-10-07 15:21:48 +00:00
weichen 5abb231efe Repair orphan tool-call tails on resume and stop mutating memory on Stop.Replacement (N3 WP1)
ci / vet-and-test (pull_request) Successful in 50s
ci / docker-checkout-hostgateway (pull_request) Successful in 1s
Why: a kill between persist(assistant) and commitToolIntent left an
unpaired tail that no recovery path repaired (acceptance clause 1's
library gap), and Stop.Replacement mutated the in-memory assistant
while the transcript kept the original (audit N6 residual).
Evidence: GOWORK=off go vet + go test -count=1 ./... green;
TestResumePairsOrphanTailAfterCrashWindow (no-intent window pairs with
crashInterrupted, run continues), TestResumeMixedIntentAndOrphanTail
(intent path and tail repair never double-pair),
TestRepairOrphanTailNoopOnHealthyTranscript; the harness assertion now
pins replacement-as-user-note (forged=4, notes=3).
Impact: every next Run repairs the trailing assistant's resultless
calls before the first request; replacement text now appears only as a
user message in both memory and transcript (intentional, recorded in
the N3 card).
Refs: Agent-System-Documents#43 (N3 plan WP1)
2026-10-07 15:02:16 +00:00
weichen ae42c9402d Spill cleared tool results to disk and pin the cache-stability contract (N2 WP1)
ci / vet-and-test (pull_request) Successful in 52s
ci / docker-checkout-hostgateway (pull_request) Successful in 1s
Why: the completion doc's N2 requires old tool results to become file
paths (ZCode compact pattern) and cache-friendly prefix rules; today the
micro-compactor only left a transcript pointer and nothing pinned prefix
stability. alignToolTail had no direct edge tests.
Evidence: GOWORK=off go vet + go test -count=1 ./... green; new
TestClearOldToolResultsSpillsToDisk / TestSpillResultSanitizesCallID /
TestAlignToolTailEdges / TestSystemTextDeterministicAcrossIdenticalBuilds;
legacy placeholder bytes unchanged when ResultsDir is empty
(TestClearOldToolResultsEmptyDirKeepsLegacyPlaceholder).
Impact: opt-in via Config.ResultsDir; the native adapter wires it to
<workDir>/.agentx/results. No behavior change for other hosts.
Refs: 2026-10-07-agent-stack-n2-plan WP1
2026-10-07 12:59:05 +00:00
weichen 948ca36ca2 Add AgentSpec, three guardrail ports, subagent events, and ask passthrough
ci / vet-and-test (pull_request) Successful in 47s
ci / docker-checkout-hostgateway (pull_request) Successful in 0s
Why: N1 increment three (WP1/WP4) - agents need a canonical spec
format with plugin restrictions, hosts need typed input/output/tool
guardrails, delegation needs lifecycle events, and squad adapters
need to pass the permission ask port through.

Evidence: go vet clean; go test ./... 26 packages ok, including new
agentspec (12 tests), guardrails (5), loop_guardrails (5), and
subagent hook tests (3).

Impact: new runtime/agentspec and runtime/guardrails packages; loop
consumes UserPromptSubmit outcomes (deny skips the loop, modify
appends the rewrite); subagent gains RegisterWithHooks emitting
SubagentStart/Stop around delegation; GateOptions gains PermissionAsk
forwarded into the kernel config. All additions are opt-in: nil
ports preserve prior behavior exactly.

Refs: Documents proposal 2026-10-07-agent-stack-n1q1i1-plans.md WP1/WP4
2026-10-07 05:04:58 +00:00
weichen 9758a8d8d0 Add permission ask loop, lifecycle hook emissions, and Policy type
ci / vet-and-test (pull_request) Successful in 48s
ci / docker-checkout-hostgateway (pull_request) Successful in 1s
Why: The N1 harness phase needs the kernel to resolve ask decisions
through the host (paired HITL), emit the full hook lifecycle the plan
promises, and carry mode/rules/session-allow in one named object.

Evidence: go vet clean; go test ./... 24 packages ok, including new
loop_hooks_lifecycle_test.go (lifecycle order, prompt text, ask
allow/deny/legacy paths, stop continuation counts) and three new
policy tests (struct-form parity, session-allow store, nil store).

Impact: hooks adds PostToolBatch and SessionEnd events; loop emits
SessionStart/UserPromptSubmit/PostToolBatch/SessionEnd and PreCompact
lands in AgentSession.Compact; gateTool consults PermissionAsk on ask
and keeps ask=reject when the port is unset; policy gains Policy,
SessionAllows, and MemoryAllows. SubagentStart/Stop emissions are
deferred to the adapters assembly increment (factory site has no bus
access yet).

Refs: Documents proposal 2026-10-07-agent-stack-n1q1i1-plans.md WP2/WP3
2026-10-07 03:01:17 +00:00
weichenandCursor fb2b3b796c Record tool intent before execution and add file checkpoints
ci / vet-and-test (pull_request) Successful in 46s
ci / docker-checkout-hostgateway (pull_request) Successful in 1s
Why: a crash after a tool was about to run left the call unpaired, and workspace writes could not be rewound.
Evidence: GOWORK=off go test ./runtime/ ./runtime/llm/ ./runtime/checkpoint/ ./runtime/telemetry/ ./runtime/tools/ ./runtime/session/ ./adapters/native/
Impact: pending calls rerun only when both the stored and current replay declarations are safe; otherwise the result is an error. Empty fallback lists and a nil checkpoint log keep the previous behavior.
Refs: feature/durable-rewind
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-03 17:27:04 +00:00
weichenandCursor 0a52d9f976 Add a hook bus and permission decisions for tool calls
ci / vet-and-test (pull_request) Successful in 46s
ci / docker-checkout-hostgateway (pull_request) Successful in 1s
Why: Squad members never saw the direct-run stop, reminder, and before-tool gates, and there was no shared place to decide deny, ask, or allow.
Evidence: GOWORK=off go test ./runtime/hooks/ ./runtime/policy/ ./runtime/ ./adapters/native/ passed, including an A/B run where hook adapters match the old callbacks.
Impact: An empty bus leaves stop reason, reminder count, and deny count unchanged. Callers opt in by setting GateOptions.
Refs: feature/permission-hooks
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-03 17:02:28 +00:00
weichenandCursor 6fd1d441a9 Keep tool pairs and fold reminders into the last result
ci / vet-and-test (pull_request) Successful in 45s
ci / docker-checkout-hostgateway (pull_request) Successful in 1s
Why: Old tool results were filling the window, compaction could split a tool group or commit a stale summary, and reminders arrived as extra user messages.
Evidence: Compaction retries a conflict and opens the circuit after three failures; clearing keeps the last five tool results; a stale file write is rejected; RPC reports started, queued, or handled.
Impact: Requests over the context window replace older tool results with a placeholder. Rewriting an existing file now requires a read in the same run. Subagent text over 32000 characters is capped.
Refs: feature/context-engineering
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-03 16:19:36 +00:00
weichenandCursor 9f5751c205 Retry model streams only before the first delta
ci / vet-and-test (pull_request) Successful in 47s
ci / docker-checkout-hostgateway (pull_request) Successful in 1s
Why: Buffering a whole attempt hid live output, overflow detection missed common provider errors, and a cut-off tool call could still run.
Evidence: GOWORK=off go test -race -count=1 ./runtime/llm/ ./runtime/ passed.
Impact: WithRetry forwards events immediately and retries only when nothing has been forwarded. Length or an unclean end drops unfinished tool calls. Loop usage keeps a billing sum and the last request separately.
Refs: feature/llm-robustness
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-03 15:52:08 +00:00
weichenandCursor 17f2a4ecfa Close the native P1 gaps the audit listed for this batch
Why: token budget let the current tool batch run, compaction could split a tool pair or race an append, writes were not crash-atomic, and several MCP and session edges only existed as comments.
Evidence: GOWORK=off go test -count=1 -race ./runtime/ ./runtime/llm/ ./runtime/session/ ./runtime/tools/ ./runtime/mcp/ ./adapters/native/ ./adapters/intentgate/ passed, including the TestR2* cases for budget, replacement, cancel, compaction, SSE, UTF-8, schema, MCP retry, session terminate, poison reload, and registry reload.
Impact: over-budget tool calls are skipped and paired; Stop.Replacement is appended to the session; the intent gate can follow Registry.Reload.
Refs: N5, N6, N7, N8, N9, N11, N12, N15, N16, N17, N18, N19, N21, I9
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-03 13:05:58 +00:00
weichenandCursor 694b08cdbe Pair skipped tool calls and close the stdio and fetch gaps
ci / vet-and-test (pull_request) Failing after 2s
ci / docker-checkout-hostgateway (pull_request) Successful in 2s
Why: a tool-budget stop left tool calls without results, host callbacks raced, a canceled MCP read stole the next response, and fetch re-resolved after the SSRF check.
Evidence: GOWORK=off go vet ./... && go test -count=1 ./... && go test -race ./runtime/... ./adapters/native/... passed, including TestLoopBudgetToolCallCap, TestParallelHostCallbacksAreSerial, TestStdioSlowCancelThenEcho, TestPresetsAndClientForChatCompletions, TestFetchResolveChangesToLoopbackRejected, and TestFetchHostCheckRedirectStillRejectsPrivate.
Impact: over-budget calls get an error result and no tool event; one Run serializes host callbacks; MCP dispatches by id; anthropic and google presets use OpenAI-compatible chat endpoints; fetch dials the address it just checked. deps/agent-intent is 3130190; error-code-system and logging-system are a3ee67b and 49b5d8b.
Refs: N1, N2, N3, N4, N13, N14
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-03 01:10:29 +00:00
weichenandCursor c6d867cde7 Let length continuations and Anthropic output run unbounded
ci / vet-and-test (pull_request) Failing after 1m30s
ci / docker-checkout-hostgateway (pull_request) Failing after 7m5s
Why: A fixed continuation cap and a 4096-token Anthropic fallback stopped long replies before the agent finished.
Evidence: go test ./runtime/ ./runtime/llm/
Impact: MaxLengthContinuations of 0 keeps the old cap of 3; a negative value removes it. Unset Anthropic max_tokens defaults to 128000.
Refs: feature/stream-display-overhaul
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-02 02:11:43 +00:00
weichenandCursor a34689c78f Delegate unregistered tool calls when a fallback is set
ci / vet-and-test (pull_request) Failing after 2m48s
ci / docker-checkout-hostgateway (pull_request) Failing after 31s
Why: the direct chat path still executes model-emitted calls that are not in the profile allow-list, while squad keeps the unknown-tool error when the fallback is unset.
Evidence: go test ./runtime/ passed, including TestLoopUnknownToolFallsThrough and the existing unknown-tool cases.
Impact: Config.UnknownTool is optional. Nil preserves today's registry error.
Refs: feature/agent-harness-p1
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-01 13:27:36 +00:00
weichenandCursor e2815bbf94 Report token usage on each message end
Why: the direct-path adapter accounts usage per turn, including runs that stop on a budget error before the final usage event.
Evidence: go test ./runtime/ ./runtime/llm/ after the field was added.
Impact: message_end and usage events carry TotalTokens. Callers that ignore the new field are unchanged.
Refs: feature/agent-harness-p1
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-01 13:25:58 +00:00
weichenandCursor 35f65a3c49 Add optional stop, reminder, and continuation hooks to the turn loop
Why: the direct chat path needs one shared loop for deliverable checks, tool pairing, reminders, and truncated replies, while squad callers keep today's behavior when the new fields stay unset.
Evidence: go test ./... in agent-native passed, including Stop cap, BeforeTool pairing, reminders absent from the session, repeat-guard cap, length continuation, and zero-value loop tests.
Impact: runtime.Config and llm.Event grow optional fields; AgentSession.Prompt copies them through. Squad sessions that leave them zero are unchanged.
Refs: feature/agent-harness-p1
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-01 13:23:07 +00:00
weichenandCursor 2dedc0d20c Add an AgentSession with steer and follow-up queues
Why: Steering hooks existed on the loop but nothing owned the queues, abort, or a model change during a run.
Evidence: go test -count=1 ./runtime/
Impact: Run still emits the existing event names. message_start, tool_execution_update, and agent_settled are added beside them.
Refs: feature/pi-headless N3
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-01 10:11:19 +00:00
weichenandCursor 951c141f95 Let hosts register tools and observe token usage
Why: product runners need register_artifact and card tools inside the kernel loop, and the UI needs token usage on the same event stream as text and tool calls.
Evidence: go test ./... in agent-native; TestHostToolAndUsageEvent and TestHostToolNameConflictFailsClosed.
Impact: Options.HostTools fail closed on name clashes; ProcessEvent and runtime events gain a usage type with token counts. Existing callers that ignore unknown event types stay compatible.
Refs: deliverable-quality-system B1
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-01 08:57:21 +00:00
weichen dd2ac11b31 Extend exec.Request with capability fields and enforce budgets end to end
Why: the frozen exec port could not express per-request model, tool
allowlist, skills, budget, or identifiers, so squad roles and product
profiles had no way to steer one execution; contract v0.1.0 semantics
(budget/cancel) stayed unconsumed (parity-matrix #4/#10/#16).

Evidence: go vet ./... clean; go test ./... all ok, including new
loop budget caps (tool calls, prompt tokens, deadline), cancel
propagation into a blocking tool, registry Restrict fail-closed
policy tests, native adapter v2 tests (model override, allowlist,
deadline-bound context, execution-id log header, skills prompt line),
and settle classification marking budget_exceeded permanent.

Impact: exec.Request gains optional Model/ToolAllowlist/Skills/Budget/
SessionScope/ExecutionID/Env (zero value = legacy behavior); runtime
loop enforces a shared budget and emits budget_exceeded events;
adapters/native consumes all new fields. Consumers on the old port
keep compiling and behaving identically.

Refs: docs/parity-matrix.md rows #4/#10/#16 (Batch2 scope); deps/
development-guidelines standards/agent-execution.md (shared budget
across retry layers).
2026-10-01 05:26:19 +00:00
weichenandCursor e65c6ba604 Align execution errors with the shared catalog and add optional logs.
Contract codes now use the agent.* values, and runtime can emit structured logs without changing results when no logger is configured.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-29 14:24:11 +00:00
weichenandCursor fedf671a48 Import the current agent-native module as a fresh history.
ci / vet-and-test (push) Successful in 5s
ci / docker-checkout-hostgateway (push) Successful in 3s
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-29 12:29:04 +00:00