Skip to content

Commit 9e6a6ad

Browse files
authored
Merge pull request #431 from EmberAGI/next
Next
2 parents 7e99ada + 634ba89 commit 9e6a6ad

File tree

184 files changed

+12828
-2533
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

184 files changed

+12828
-2533
lines changed

.actrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-P ubuntu-latest=ghcr.io/catthehacker/ubuntu:act-latest
2+
--container-architecture linux/amd64

.github/workflows/ci.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ on:
44
push:
55
branches: [main, master]
66
pull_request:
7-
paths:
8-
- "typescript/**"
9-
- ".github/workflows/ci.yml"
7+
merge_group:
8+
branches: [main, master, next]
109
workflow_dispatch:
1110

1211
jobs:
@@ -25,12 +24,12 @@ jobs:
2524
- name: Setup pnpm
2625
uses: pnpm/action-setup@v4
2726
with:
28-
version: 10
27+
version: 10.7.0
2928
run_install: false
3029

3130
- name: Install dependencies in project
3231
working-directory: ./typescript
33-
run: pnpm install --no-frozen-lockfile
32+
run: pnpm install --frozen-lockfile
3433

3534
- name: Run linter
3635
working-directory: ./typescript

.github/workflows/onchain-actions.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ jobs:
2626
- name: Setup pnpm
2727
uses: pnpm/action-setup@v4
2828
with:
29-
version: 10
29+
version: 10.7.0
3030
run_install: false
3131

3232
- name: Install dependencies in project
3333
working-directory: ./typescript
34-
run: pnpm install --no-frozen-lockfile
34+
run: pnpm install --frozen-lockfile
3535

3636
- name: Install Foundry
3737
uses: foundry-rs/foundry-toolchain@v1

docs/merge-queue-runbook.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Merge Queue Runbook
2+
3+
## Purpose
4+
5+
This runbook prevents PR-head vs merge-ref drift by enforcing CI in merge context and serializing merges through GitHub merge queue.
6+
7+
## Required repository settings
8+
9+
- `CI` workflow includes `merge_group` trigger.
10+
- Branch rulesets for `next` and default branch require:
11+
- Strict required status checks (`build`).
12+
- Merge queue enabled.
13+
14+
## Daily workflow
15+
16+
1. Open PR as usual and wait for required checks.
17+
2. Resolve review feedback and re-run checks.
18+
3. Use merge queue instead of direct merge.
19+
4. Let queue revalidate in merge context before final merge.
20+
21+
## When to run a local merge-ref check (optional)
22+
23+
Run local parity checks when a PR is high-risk or multiple related PRs are landing together.
24+
25+
Recommended quick check:
26+
27+
```bash
28+
act merge_group -W .github/workflows/ci.yml -n
29+
```
30+
31+
If you suspect integration conflicts, run a local merge-ref simulation and verify lint/build:
32+
33+
```bash
34+
git fetch origin pull/<PR_NUMBER>/head:pr-head pull/<PR_NUMBER>/merge:pr-merge
35+
git diff pr-head..pr-merge -- <path/to/suspect/file>
36+
pnpm -C typescript lint
37+
pnpm -C typescript build
38+
```
39+
40+
## Operational notes
41+
42+
- Keep admin bypasses rare; bypassing queue weakens merge guarantees.
43+
- If queue latency grows, tune merge queue batch settings before disabling protection.

typescript/clients/web-ag-ui/apps/agent-clmm/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"test": "pnpm test:unit && pnpm test:int && pnpm test:e2e",
1313
"test:unit": "vitest run --config vitest.config.unit.ts",
1414
"test:int": "bash -lc 'ENV_FILE=.env.test; [ -f \"$ENV_FILE\" ] || ENV_FILE=.env.test.example; exec tsx --env-file=\"$ENV_FILE\" ./node_modules/vitest/vitest.mjs run --config vitest.config.int.ts \"$@\"' --",
15-
"test:e2e": "bash -lc 'ENV_FILE=.env.test; [ -f \"$ENV_FILE\" ] || ENV_FILE=.env.test.example; exec tsx --env-file=\"$ENV_FILE\" ./node_modules/vitest/vitest.mjs run --config vitest.config.e2e.ts --no-file-parallelism --maxConcurrency=1 \"$@\"' --",
15+
"test:e2e": "bash -lc 'ENV_FILE=.env.test; [ -f \"$ENV_FILE\" ] || ENV_FILE=.env.test.example; CLMM_E2E=\"${CLMM_E2E:-true}\" LANGGRAPH_DEPLOYMENT_URL=\"${LANGGRAPH_DEPLOYMENT_URL:-http://localhost:8124}\" exec tsx --env-file=\"$ENV_FILE\" ./node_modules/vitest/vitest.mjs run --config vitest.config.e2e.ts --no-file-parallelism --maxConcurrency=1 \"$@\"' --",
1616
"test:watch": "vitest watch",
1717
"test:ci": "pnpm test:unit && pnpm test:int",
1818
"lint": "eslint \"src\" \"tests\" --ext .ts",

typescript/clients/web-ag-ui/apps/agent-clmm/src/agent.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,28 @@ import { extractCommand, resolveCommandTarget, runCommandNode } from './workflow
3131
import { runCycleCommandNode } from './workflow/nodes/runCycleCommand.js';
3232
import { summarizeNode } from './workflow/nodes/summarize.js';
3333
import { syncStateNode } from './workflow/nodes/syncState.js';
34+
import { resolveNextOnboardingNode } from './workflow/onboardingRouting.js';
3435
import { saveBootstrapContext } from './workflow/store.js';
3536

3637
/**
3738
* Routes after bootstrap based on the original command.
3839
* - sync: go to syncState (just return state after bootstrap)
39-
* - hire/cycle: continue to listPools for full setup flow
40+
* - hire/cycle: resume from the next missing onboarding requirement
4041
*/
41-
function resolvePostBootstrap(state: ClmmState): 'listPools' | 'syncState' {
42+
function resolvePostBootstrap(
43+
state: ClmmState,
44+
):
45+
| 'listPools'
46+
| 'collectOperatorInput'
47+
| 'collectFundingTokenInput'
48+
| 'collectDelegations'
49+
| 'prepareOperator'
50+
| 'syncState' {
4251
const command = extractCommand(state.messages) ?? state.view.command;
43-
return command === 'sync' ? 'syncState' : 'listPools';
52+
if (command === 'sync') {
53+
return 'syncState';
54+
}
55+
return resolveNextOnboardingNode(state);
4456
}
4557

4658
const store = new InMemoryStore();

typescript/clients/web-ag-ui/apps/agent-clmm/src/domain/types.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,13 @@ const EmberPoolTokenSchema = z.object({
5858
symbol: z.string(),
5959
decimals: z.number().int().nonnegative(),
6060
isNative: z.boolean().optional(),
61-
iconUri: z.string().optional(),
61+
// Ember occasionally returns `null` for iconUri; normalize to `undefined` so
62+
// pool listing doesn't fail due to a missing icon.
63+
iconUri: z
64+
.string()
65+
.nullable()
66+
.optional()
67+
.transform((value) => value ?? undefined),
6268
isVetted: z.boolean().optional(),
6369
});
6470

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { describe, expect, it } from 'vitest';
2+
3+
import { PoolListResponseSchema } from './types.js';
4+
5+
describe('PoolListResponseSchema', () => {
6+
it('accepts null token iconUri from Ember API and normalizes to undefined', () => {
7+
const parsed = PoolListResponseSchema.parse({
8+
liquidityPools: [
9+
{
10+
identifier: { chainId: '42161', address: '0xpool' },
11+
tokens: [
12+
{
13+
tokenUid: { chainId: '42161', address: '0xtoken0' },
14+
name: 'Token0',
15+
symbol: 'T0',
16+
decimals: 18,
17+
iconUri: null,
18+
},
19+
{
20+
tokenUid: { chainId: '42161', address: '0xtoken1' },
21+
name: 'Token1',
22+
symbol: 'T1',
23+
decimals: 18,
24+
},
25+
],
26+
currentPrice: '1',
27+
providerId: 'camelot',
28+
poolName: 'T0/T1',
29+
},
30+
],
31+
});
32+
33+
expect(parsed.liquidityPools[0]?.tokens[0]?.iconUri).toBeUndefined();
34+
});
35+
});
36+

typescript/clients/web-ag-ui/apps/agent-clmm/src/workflow/context.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export type ClmmActivity = {
6464
events: ClmmEvent[];
6565
};
6666

67-
export type ClmmTransaction = {
67+
export type AgentTransaction = {
6868
cycle: number;
6969
action: string;
7070
txHash?: string;
@@ -221,7 +221,7 @@ type ClmmViewState = {
221221
profile: ClmmProfile;
222222
activity: ClmmActivity;
223223
metrics: ClmmMetrics;
224-
transactionHistory: ClmmTransaction[];
224+
transactionHistory: AgentTransaction[];
225225
accounting: ClmmAccounting;
226226
delegationsBypassActive?: boolean;
227227
};

typescript/clients/web-ag-ui/apps/agent-clmm/src/workflow/historyStore.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type { NavSnapshot, FlowLogEvent } from '../accounting/types.js';
55
import { resolveStoreHistoryLimit } from '../config/constants.js';
66
import type { RebalanceTelemetry } from '../domain/types.js';
77

8-
import type { ClmmTransaction } from './context.js';
8+
import type { AgentTransaction } from './context.js';
99

1010
const STORE_HISTORY_LIMIT = resolveStoreHistoryLimit();
1111

@@ -88,7 +88,7 @@ export async function appendTelemetryHistory(params: {
8888

8989
export async function appendTransactionHistory(params: {
9090
threadId?: string;
91-
transactions: ClmmTransaction[];
91+
transactions: AgentTransaction[];
9292
store?: BaseStore;
9393
}): Promise<void> {
9494
await appendHistory({

0 commit comments

Comments
 (0)