Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
dc87a81
fix(k8s): restart iron-proxy containers on failure (#1523)
Zygimantass Aug 28, 2026
1d5a0d5
feat: bind the comment author's principal on GitHub turns (#1496)
cjustice Aug 30, 2026
d8523f7
feat: promote company context embeddings (#1565)
mslipper Aug 31, 2026
1e23712
fix: resolve Granola share links via note details (#1571)
decofe Aug 31, 2026
f98634e
feat: add experimental memory generation workflow (#1574)
mslipper Aug 31, 2026
fd3c260
Set default Codex reasoning to medium (#1573)
svc-paradigm Sep 1, 2026
80ebdf9
feat: add Centaur agent plugin registry (#1584)
brendanjryan Sep 1, 2026
f5ef8b8
Retry transient console sync connection failures (#1587)
svc-paradigm Sep 1, 2026
afa5081
fix(slack): use canonical message permalinks (#1590)
decofe Sep 2, 2026
f7c7e0c
feat: trace MCP tool calls in Laminar (#1591)
mslipper Sep 2, 2026
fd05f83
fix: pin personas for thread lifetime (#1595)
mslipper Sep 4, 2026
958173b
feat: add console chat sunset controls (#1596)
mslipper Sep 4, 2026
609f200
fix: hide Slack console links when chat is disabled (#1597)
mslipper Sep 4, 2026
619a753
feat: add GPT-6-Astra support (#1599)
decofe Sep 4, 2026
dafff4c
fix: retry Granola MCP server errors (#1602)
svc-paradigm Sep 4, 2026
48bbe92
fix: fall back from unavailable personas (#1598)
mslipper Sep 4, 2026
312b427
fix(k8s): own iron-proxy resources and reap orphans (#1529)
0xAlcibiades Sep 4, 2026
e00c5bc
fix(session-runtime): report why a sandbox died, not just that it did…
0xAlcibiades Sep 4, 2026
aa2be36
fix(api-rs): send a reasoning effort on the title and summary calls (…
0xAlcibiades Sep 4, 2026
886eee7
fix(githubbot): log output size on review, issue and management turns…
0xAlcibiades Sep 4, 2026
b4bb8d8
feat(linearbot): per-turn-type reasoning effort (#1539)
0xAlcibiades Sep 4, 2026
55bf331
feat(company-context): make the embedding dimension configurable (#1533)
0xAlcibiades Sep 4, 2026
280f838
feat: allow reading Google Docs comments (#1605)
mslipper Sep 5, 2026
5499d94
chore(deps): bump uuid from 1.24.1 to 1.26.0 in /services/api-rs in t…
dependabot[bot] Sep 5, 2026
dd3eb03
chore(deps): bump re-actors/alls-green from 1.2.2 to 1.3.0 in the git…
dependabot[bot] Sep 5, 2026
1ac3ef3
chore(deps): bump the ruby-dependencies group in /services/console wi…
dependabot[bot] Sep 5, 2026
06061cd
chore(deps): bump uuid from 1.24.1 to 1.26.0 in /crates/harness-serve…
dependabot[bot] Sep 5, 2026
4c3d5a2
Point Claude aliases and defaults at Opus 5 and Sonnet 5 (#1485)
ivpusic Sep 5, 2026
d3143c3
fix: terminalize structured workflow host errors (#1482)
PengDeng-Cyber Sep 5, 2026
b78c4c3
chore(deps): bump the github-actions group with 2 updates (#1613)
dependabot[bot] Sep 7, 2026
e0159af
chore(deps): bump the api-rs-dependencies group in /services/api-rs w…
dependabot[bot] Sep 7, 2026
867c054
chore(deps): bump the ruby-dependencies group in /services/console wi…
dependabot[bot] Sep 7, 2026
0715475
chore(slackbotv2): upgrade Chat SDK to 4.40.0 (#1615)
mslipper Sep 8, 2026
353eb02
merge: integrate paradigmxyz centaur main
michaelmwu Sep 8, 2026
3299fb0
fix: preserve migration order in upstream integration
michaelmwu Sep 8, 2026
a258257
fix: configure orphan sweep in reaper test
michaelmwu Sep 8, 2026
483aa62
fix: attach iron-control test helper docs
michaelmwu Sep 8, 2026
f7974b2
fix: validate plugin versions and neutralize proxy guidance
michaelmwu Sep 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .agents/plugins/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "centaur",
"interface": {
"displayName": "Centaur"
},
"plugins": [
{
"name": "centaur",
"source": {
"source": "local",
"path": "./plugins/centaur"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL"
},
"category": "Developer Tools"
}
]
}
27 changes: 27 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "centaur",
"owner": {
"name": "Paradigm",
"url": "https://github.com/paradigmxyz"
},
"description": "Official Centaur plugins for agent clients.",
"version": "0.1.0",
"plugins": [
{
"name": "centaur",
"displayName": "Centaur",
"source": "./plugins/centaur",
"description": "Use your team's approved Centaur tools through MCP.",
"version": "0.1.0",
"author": {
"name": "Paradigm",
"url": "https://github.com/paradigmxyz"
},
"homepage": "https://centaur.run",
"repository": "https://github.com/paradigmxyz/centaur",
"license": "Apache-2.0 OR MIT",
"keywords": ["centaur", "mcp", "tools", "agents"],
"category": "developer-tools"
}
]
}
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ jobs:
'^package\.json$' \
'^pnpm-lock\.yaml$' \
'^pnpm-workspace\.yaml$' \
'^patches/' \
'^\.github/workflows/ci\.yml$'
set_output discordbot_checks \
'^services/discordbot/' \
Expand Down Expand Up @@ -540,7 +541,7 @@ jobs:
timeout-minutes: 30
steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2
uses: re-actors/alls-green@b5b5b37504aa4183270bd3d855c52a67f212be35 # v1.3.0
with:
allowed-skips: migration-order, harness-server-checks, rust-api, sandbox-tests, workflow-python-tests, tool-tests, slackbotv2-tests, discordbot-checks, githubbot-checks, teamsbot-checks
jobs: ${{ toJSON(needs) }}
2 changes: 1 addition & 1 deletion .github/workflows/console-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ jobs:
working-directory: .
steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2
uses: re-actors/alls-green@b5b5b37504aa4183270bd3d855c52a67f212be35 # v1.3.0
with:
allowed-skips: scan_ruby, scan_js, lint, test
jobs: ${{ toJSON(needs) }}
33 changes: 33 additions & 0 deletions .github/workflows/validate-agent-plugin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Validate agent plugin

on:
push:
paths:
- ".agents/plugins/**"
- ".claude-plugin/**"
- "plugins/centaur/**"
- "scripts/validate_agent_plugin.py"
- "scripts/test_validate_agent_plugin.py"
- ".github/workflows/validate-agent-plugin.yml"
pull_request:
paths:
- ".agents/plugins/**"
- ".claude-plugin/**"
- "plugins/centaur/**"
- "scripts/validate_agent_plugin.py"
- "scripts/test_validate_agent_plugin.py"
- ".github/workflows/validate-agent-plugin.yml"

permissions:
contents: read

jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: "3.11"
- run: python scripts/test_validate_agent_plugin.py
- run: python scripts/validate_agent_plugin.py
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ services/sandbox/repos/
# Agent / AI IDE config
.agents/*
!.agents/skills/
!.agents/plugins/
.agents/plugins/*
!.agents/plugins/marketplace.json
.amp/
.claude/
.cursor/
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ See [Security](docs/pages/security.mdx) for the full threat model and the mechan
- [Developer Guide](AGENTS.md) — full local setup, architecture, API contracts, migrations, testing, and conventions
- [Tools](tools/) — built-in tool plugins
- [Workflows](workflows/) — external workflow plugins
- [Agent plugin](plugins/centaur/) — connect Codex, Claude Code, and other MCP clients to Centaur
- [API service](services/api-rs/) — Rust control plane
- [Slackbot](services/slackbotv2/) — Slack integration
- [Sandbox](services/sandbox/) — agent runtime image
Expand Down
2 changes: 1 addition & 1 deletion contrib/chart/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: v2
name: centaur
description: Helm chart for the trusted Centaur control plane
type: application
version: 0.1.137
version: 0.1.138
appVersion: "0.1.0"
dependencies:
- name: connect
Expand Down
10 changes: 10 additions & 0 deletions contrib/chart/templates/apirs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
{{- $apiRsEtl := .Values.apiRs.etl | default dict -}}
{{- $companyContextEmbeddingsEnabled := dig "companyContextEmbeddings" "enabled" false $apiRsEtl -}}
{{- $companyContextEmbeddingsModel := dig "companyContextEmbeddings" "model" "text-embedding-3-small" $apiRsEtl -}}
{{- $companyContextEmbeddingsDimensions := dig "companyContextEmbeddings" "dimensions" 1536 $apiRsEtl -}}
{{- $apiRsEtlEnv := list
(dict "name" "SLACK_ETL_ENABLED" "value" (dig "slack" "enabled" false $apiRsEtl))
(dict "name" "SLACK_SYNC_INTERVAL_SECONDS" "value" (dig "slack" "syncIntervalSeconds" 3600 $apiRsEtl))
Expand Down Expand Up @@ -108,7 +109,9 @@
(dict "name" "COMPANY_CONTEXT_EMBEDDINGS_ENABLED" "value" $companyContextEmbeddingsEnabled)
(dict "name" "COMPANY_CONTEXT_EMBEDDINGS_INTERVAL_SECONDS" "value" (dig "companyContextEmbeddings" "intervalSeconds" 300 $apiRsEtl))
(dict "name" "COMPANY_CONTEXT_EMBEDDINGS_BATCH_SIZE" "value" (dig "companyContextEmbeddings" "batchSize" 250 $apiRsEtl))
(dict "name" "COMPANY_CONTEXT_EMBEDDINGS_MAX_INPUT_CHARS" "value" (dig "companyContextEmbeddings" "maxInputChars" 8192 $apiRsEtl))
(dict "name" "COMPANY_CONTEXT_EMBEDDINGS_MODEL" "value" $companyContextEmbeddingsModel)
(dict "name" "COMPANY_CONTEXT_EMBEDDINGS_DIMENSIONS" "value" $companyContextEmbeddingsDimensions)
-}}
{{- $apiRsEtlPassthroughNames := list -}}
{{- range $env := $apiRsEtlEnv -}}
Expand Down Expand Up @@ -340,6 +343,8 @@ spec:
value: {{ .Values.apiRs.sandboxMaxLifetimeSecs | quote }}
- name: SESSION_SANDBOX_REAP_INTERVAL_SECS
value: {{ .Values.apiRs.sandboxReapIntervalSecs | quote }}
- name: SESSION_SANDBOX_ORPHAN_SWEEP_GRACE_SECS
value: {{ .Values.apiRs.sandboxOrphanSweepGraceSecs | quote }}
- name: SESSION_SANDBOX_CLEANUP_INTERVAL_SECS
value: {{ .Values.apiRs.sandboxCleanupIntervalSecs | quote }}
- name: SESSION_SANDBOX_IDLE_CLEANUP_BACKSTOP_SECS
Expand All @@ -359,6 +364,8 @@ spec:
value: {{ .Values.apiRs.activitySummary.maxFacts | quote }}
- name: SESSION_ACTIVITY_SUMMARY_MAX_OUTPUT_TOKENS
value: {{ .Values.apiRs.activitySummary.maxOutputTokens | quote }}
- name: SESSION_ACTIVITY_SUMMARY_REASONING_EFFORT
value: {{ .Values.apiRs.activitySummary.reasoningEffort | default "" | quote }}
{{- end }}
- name: SESSION_SANDBOX_K8S_NAMESPACE
value: {{ .Release.Namespace | quote }}
Expand Down Expand Up @@ -476,6 +483,9 @@ spec:
{{- if not (hasKey .Values.sandbox.extraEnv "COMPANY_CONTEXT_EMBEDDINGS_MODEL") }}
{{- $sandboxEnvList = append $sandboxEnvList (dict "name" "COMPANY_CONTEXT_EMBEDDINGS_MODEL" "value" $companyContextEmbeddingsModel) }}
{{- end }}
{{- if not (hasKey .Values.sandbox.extraEnv "COMPANY_CONTEXT_EMBEDDINGS_DIMENSIONS") }}
{{- $sandboxEnvList = append $sandboxEnvList (dict "name" "COMPANY_CONTEXT_EMBEDDINGS_DIMENSIONS" "value" ($companyContextEmbeddingsDimensions | toString)) }}
{{- end }}
{{- if .Values.codex.customProviders }}
{{- $sandboxEnvList = append $sandboxEnvList (dict "name" "CODEX_CUSTOM_PROVIDERS" "value" (.Values.codex.customProviders | toJson)) }}
{{- end }}
Expand Down
2 changes: 2 additions & 0 deletions contrib/chart/templates/console.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,8 @@ spec:
{{- end }}
- name: CENTAUR_CONSOLE_PASSWORD_LOGIN_ENABLED
value: {{ $console.passwordLoginEnabled | quote }}
- name: CENTAUR_CONSOLE_CHAT_ENABLED
value: {{ $console.chat.enabled | quote }}
- name: CENTAUR_CONSOLE_PUBLIC_SLACK_THREADS_ENABLED
value: {{ $console.publicSlackThreadsEnabled | quote }}
{{- with $console.ssoEmailDomains }}
Expand Down
10 changes: 10 additions & 0 deletions contrib/chart/templates/linearbot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@ spec:
key: {{ printf "%sDATABASE_URL" .Values.secretManager.envPrefix }}
- name: LINEARBOT_USER_NAME
value: {{ .Values.linearbot.userName | quote }}
{{- with .Values.linearbot.reasoningEffort }}
{{- if .assignment }}
- name: LINEARBOT_EFFORT_ASSIGNMENT
value: {{ .assignment | quote }}
{{- end }}
{{- if .comment }}
- name: LINEARBOT_EFFORT_COMMENT
value: {{ .comment | quote }}
{{- end }}
{{- end }}
{{- if .Values.codex.customProviders }}
- name: CODEX_CUSTOM_PROVIDERS
value: {{ .Values.codex.customProviders | toJson | quote }}
Expand Down
7 changes: 4 additions & 3 deletions contrib/chart/templates/slackbotv2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,11 @@ spec:
value: {{ .Values.slackbotv2.messageOverridesStrategy.timeoutMs | quote }}
- name: SLACKBOTV2_MESSAGE_OVERRIDES_MAX_OUTPUT_TOKENS
value: {{ .Values.slackbotv2.messageOverridesStrategy.maxOutputTokens | quote }}
{{- if $console.publicUrl }}
{{- if and $console.chat.enabled $console.publicUrl }}
# Public origin of the Console UI (matches the Console's own
# CENTAUR_CONSOLE_PUBLIC_URL). When set, the first assistant message
# in a Slack thread gets an "Open session in Console" link.
# CENTAUR_CONSOLE_PUBLIC_URL). When chat is enabled, the first
# assistant message in a Slack thread gets an "Open chat in Console"
# link.
- name: CENTAUR_CONSOLE_PUBLIC_URL
value: {{ $console.publicUrl | quote }}
{{- end }}
Expand Down
15 changes: 14 additions & 1 deletion contrib/chart/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@
},
"sentryDsn": { "type": "string" },
"railsEnv": { "type": "string" },
"chat": {
"type": "object",
"properties": {
"enabled": { "type": "boolean" }
}
},
"image": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -347,6 +353,7 @@
"mcpPublicUrl": { "type": "string" },
"sandboxRunningLimit": { "type": "integer", "minimum": 0 },
"sandboxHotIdleGraceSecs": { "type": "integer", "minimum": 0 },
"sandboxOrphanSweepGraceSecs": { "type": "integer", "minimum": 1 },
"workflowHostSandbox": { "type": "boolean" },
"workflowHostResources": { "type": "object" },
"actionProposalBindings": {
Expand Down Expand Up @@ -447,7 +454,13 @@
"enabled": { "type": "boolean" },
"intervalSeconds": { "type": "integer", "minimum": 1 },
"batchSize": { "type": "integer", "minimum": 1 },
"model": { "type": "string", "minLength": 1 }
"maxInputChars": {
"type": "integer",
"minimum": 1,
"maximum": 8192
},
"model": { "type": "string", "minLength": 1 },
"dimensions": { "const": 1536 }
}
}
}
Expand Down
33 changes: 31 additions & 2 deletions contrib/chart/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,9 @@ console:
# Public URL users reach in a browser (e.g. https://console.example.com), used
# as CENTAUR_CONSOLE_PUBLIC_URL. Set this when console is exposed behind
# Tailscale/Ingress so MCP OAuth issuer metadata and JWT validation agree.
# When set, the slackbotv2 deployment also links the first assistant message
# in a Slack thread to the Console session view; leave empty to omit the link.
# When set and console.chat.enabled is true, the slackbotv2 deployment also
# links the first assistant message in a Slack thread to the Console session
# view. Leave empty to omit the link.
publicUrl: ""
# Additional exact Host headers accepted by Rails Host Authorization. Use for
# service DNS names that differ from the chart's short in-cluster URL;
Expand All @@ -117,6 +118,10 @@ console:
# Break-glass email/password login. Disable when console is reachable from
# the public internet and SSO is configured.
passwordLoginEnabled: true
# Console's browser-based chat UI is deprecated and will be removed in
# October. Disable it to hide chat navigation and reject its HTTP routes.
chat:
enabled: true
# When enabled, every authenticated Console user can browse conversations
# originating in public Slack channels. Private channels and DMs remain
# owner-only. Requires apiRs.etl.slack.enabled so channel privacy is synced;
Expand Down Expand Up @@ -522,14 +527,25 @@ apiRs:
companyContextEmbeddings:
# Enables the embedding workflow and hybrid search in agent sandboxes.
enabled: false
# Delay between scheduled scans for missing or stale embeddings.
intervalSeconds: 300
# Maximum documents claimed by each workflow run.
batchSize: 250
# Maximum characters sent per document. Inputs are capped at 8192.
maxInputChars: 8192
# Shared by the embedding workflow and company-context searches in agent sandboxes.
model: text-embedding-3-small
# Vector width requested from the model by both the write and query sides.
# This must match the database column width. Changing it requires a schema
# migration, index rebuild, and re-embedding existing rows. pgvector will
# not build an HNSW or IVFFlat index above 2000.
dimensions: 1536
# Reaper: stop sandboxes older than the max lifetime, regardless of whether
# they are running or suspended. 0 disables the sweep. Interval must be >= 1.
sandboxMaxLifetimeSecs: 259200 # 3 days
sandboxReapIntervalSecs: 300
# Minimum age before proxy resources without a live Sandbox are reaped.
sandboxOrphanSweepGraceSecs: 600
# Cleanup worker: stop unreferenced session/warm-pool sandboxes after two
# consecutive sweeps and restore idle-pauses lost across api-rs restarts.
# The idle backstop is only used when older execution rows have no persisted
Expand All @@ -545,6 +561,11 @@ apiRs:
timeoutSecs: 5
maxFacts: 12
maxOutputTokens: 128
# Reasoning effort for the summary call. The output budget above is small,
# so a server that resolves an absent effort to its highest level spends
# the whole budget reasoning and returns no message. Empty omits the
# parameter, for a server that rejects it outright.
reasoningEffort: low
metrics:
# The Rust API always serves Prometheus text metrics at /metrics. This flag
# only controls scrape annotations for Prometheus/VictoriaMetrics-style
Expand Down Expand Up @@ -659,6 +680,14 @@ linearbot:
tag: latest
pullPolicy: Always
userName: centaur
# Reasoning effort per turn type (codex turn/start.effort). Both unset run at
# the harness default. These turns are autonomous, so there is no message for
# a -rsn flag to ride on, and one global setting suits neither an assignment
# turn implementing a whole ticket nor a one-line comment reply.
# Accepts none | minimal | low | medium | high | xhigh | max.
reasoningEffort:
assignment: ""
comment: ""
extraEnv: {}
resources: {}

Expand Down
4 changes: 2 additions & 2 deletions crates/harness-server/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/harness-server/src/codex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ fn run_codex_user_turn<W: Write>(
}
// Per-turn reasoning effort (codex `turn/start.effort`), parsed from the
// `-rsn` message flag. Values match codex's ReasoningEffort enum
// (none|minimal|low|medium|high|xhigh|max); validation happens upstream.
// (none|minimal|low|medium|high|xhigh|max|ultra); validation happens upstream.
if let Some(reasoning) = reasoning {
params["effort"] = Value::String(reasoning);
}
Expand Down
21 changes: 20 additions & 1 deletion crates/harness-server/src/otel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1112,7 +1112,17 @@ fn anthropic_pricing(model: &str) -> Option<TokenPricing> {
source: "centaur_estimate:anthropic:fable-mythos-5:5m-cache-write",
});
}
if model.contains("opus-4-8")
if model.contains("opus-5-fast") {
return Some(TokenPricing {
input_per_mtok: 10.0,
cache_creation_per_mtok: 12.5,
cache_read_per_mtok: 1.0,
output_per_mtok: 50.0,
source: "centaur_estimate:anthropic:opus-5-fast:5m-cache-write",
});
}
if model.contains("opus-5")
|| model.contains("opus-4-8")
|| model.contains("opus-4-7")
|| model.contains("opus-4-6")
|| model.contains("opus-4-5")
Expand All @@ -1134,6 +1144,15 @@ fn anthropic_pricing(model: &str) -> Option<TokenPricing> {
source: "centaur_estimate:anthropic:opus-4-deprecated:5m-cache-write",
});
}
if model.contains("sonnet-5") {
return Some(TokenPricing {
input_per_mtok: 2.0,
cache_creation_per_mtok: 2.5,
cache_read_per_mtok: 0.2,
output_per_mtok: 10.0,
source: "centaur_estimate:anthropic:sonnet-5:5m-cache-write",
});
}
if model.contains("sonnet-4-6") || model.contains("sonnet-4-5") || model.contains("sonnet-4") {
return Some(TokenPricing {
input_per_mtok: 3.0,
Expand Down
Loading