@onride/agent 0.0.0-stage → 0.5.1-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +31 -0
- package/LICENSE +21 -0
- package/README.md +174 -2
- package/dist/account_balances.js +435 -0
- package/dist/account_reads.js +199 -0
- package/dist/agent/adapter.js +115 -0
- package/dist/agent/analytics.js +174 -0
- package/dist/agent/backend.js +237 -0
- package/dist/agent/card_hosts.js +9 -0
- package/dist/agent/contracts.js +276 -0
- package/dist/agent/conversational.js +86 -0
- package/dist/agent/core_bridge.js +1155 -0
- package/dist/agent/deposits.js +309 -0
- package/dist/agent/discovery.js +205 -0
- package/dist/agent/domain.js +507 -0
- package/dist/agent/firebase.js +34 -0
- package/dist/agent/funding.js +230 -0
- package/dist/agent/http.js +40 -0
- package/dist/agent/human.js +298 -0
- package/dist/agent/human_handoffs.js +39 -0
- package/dist/agent/ledger.js +137 -0
- package/dist/agent/mcp.js +245 -0
- package/dist/agent/order_rules.js +61 -0
- package/dist/agent/perps_account.js +41 -0
- package/dist/agent/prediction.js +607 -0
- package/dist/agent/prediction_equity_history.js +910 -0
- package/dist/agent/prediction_history.js +336 -0
- package/dist/agent/preferences.js +114 -0
- package/dist/agent/repository.js +106 -0
- package/dist/agent/runner.js +683 -0
- package/dist/agent/service.js +1347 -0
- package/dist/backend.js +6 -0
- package/dist/bridge.js +6 -0
- package/dist/cli/clients.js +99 -0
- package/dist/cli/commands.js +332 -0
- package/dist/cli/onboarding.js +53 -0
- package/dist/cli/session.js +224 -0
- package/dist/cli/setup.js +256 -0
- package/dist/cli.js +16 -0
- package/dist/guide.js +92 -0
- package/dist/http_security.js +79 -0
- package/dist/mcp-cli.js +7 -0
- package/dist/oauth.js +1032 -0
- package/dist/server.js +171 -0
- package/dist/start.js +18 -0
- package/dist/version.js +25 -0
- package/docs/confirmation-cards.md +118 -0
- package/docs/conversation-v050.md +30 -0
- package/docs/conversational-v17.md +48 -0
- package/docs/deployment.md +58 -0
- package/docs/perps-leverage.md +43 -0
- package/docs/prediction-history.md +28 -0
- package/docs/preferences-funding-v042.md +17 -0
- package/docs/ride-agent-migration.md +127 -0
- package/docs/v17-completion-checklist.md +31 -0
- package/docs/v17-rollout.md +44 -0
- package/docs/widget-account-v043.md +17 -0
- package/package.json +75 -4
- package/public/agent.html +2313 -0
- package/public/confirm.html +2373 -0
- package/public/fund.html +563 -0
- package/skills/ride/SKILL.md +18 -0
- package/skills/ride/references/commands.md +47 -0
- package/skills/ride/references/workflow.md +47 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "dotenv/config";
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { GUIDE_INSTRUCTIONS, packagedGuide, registerGuide } from "./guide.js";
|
|
5
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
6
|
+
import { mcpAuthRouter, getOAuthProtectedResourceMetadataUrl, } from "@modelcontextprotocol/sdk/server/auth/router.js";
|
|
7
|
+
import { requireBearerAuth } from "@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js";
|
|
8
|
+
import { RideOAuthProvider, InMemoryOAuthStateStore, createRedisOAuthStateStore, createRideOAuthApprovalRouter, RIDE_OAUTH_SCOPES, } from "./oauth.js";
|
|
9
|
+
import { createRideHttpApp, requestBodyErrorHandler } from "./http_security.js";
|
|
10
|
+
import { registerAgentTools, registerAppAccountRead, invokeAgent, } from "./agent/mcp.js";
|
|
11
|
+
import { invokeAccountRead } from "./account_reads.js";
|
|
12
|
+
import { mountAgentProxy } from "./agent/http.js";
|
|
13
|
+
import { mountHumanConfirmation } from "./agent/human.js";
|
|
14
|
+
import { redisHumanHandoffs } from "./agent/human_handoffs.js";
|
|
15
|
+
import { validateCoreIdentity } from "./agent/backend.js";
|
|
16
|
+
import { AgentError, mutationTools } from "./agent/contracts.js";
|
|
17
|
+
import { VERSION } from "./version.js";
|
|
18
|
+
async function main() {
|
|
19
|
+
const required = (key) => {
|
|
20
|
+
const v = process.env[key];
|
|
21
|
+
if (!v)
|
|
22
|
+
throw new Error(`${key} is required`);
|
|
23
|
+
return v;
|
|
24
|
+
};
|
|
25
|
+
const host = process.env.HOST ?? "127.0.0.1", port = Number(process.env.PORT ?? 3333), base = new URL(required("PUBLIC_BASE_URL")), backend = required("RIDE_AGENT_BACKEND_URL"), graphql = required("RIDE_GRAPHQL_URL");
|
|
26
|
+
if (base.protocol !== "https:" &&
|
|
27
|
+
!["127.0.0.1", "localhost"].includes(base.hostname))
|
|
28
|
+
throw new Error("Public issuer must use HTTPS");
|
|
29
|
+
if (!process.env.REDIS_URL &&
|
|
30
|
+
!["127.0.0.1", "localhost"].includes(base.hostname))
|
|
31
|
+
throw new Error("Hosted OAuth requires Redis");
|
|
32
|
+
const store = process.env.REDIS_URL
|
|
33
|
+
? await createRedisOAuthStateStore({ url: process.env.REDIS_URL })
|
|
34
|
+
: new InMemoryOAuthStateStore();
|
|
35
|
+
const config = {
|
|
36
|
+
privyAppId: required("PRIVY_APP_ID"),
|
|
37
|
+
privyClientId: process.env.PRIVY_CLIENT_ID ?? "",
|
|
38
|
+
jsSdkUrl: process.env.PRIVY_JS_SDK_URL ??
|
|
39
|
+
"https://esm.sh/@privy-io/js-sdk-core@0.67.0",
|
|
40
|
+
manualTokenAuthEnabled: false,
|
|
41
|
+
};
|
|
42
|
+
const exchange = async (input) => {
|
|
43
|
+
const response = await fetch(graphql, {
|
|
44
|
+
method: "POST",
|
|
45
|
+
headers: { "Content-Type": "application/json" },
|
|
46
|
+
body: JSON.stringify({
|
|
47
|
+
query: "mutation AgentLogin($input:SyncPrivyUserInput!){syncPrivyUser(input:$input){accessToken user{id username}}}",
|
|
48
|
+
variables: {
|
|
49
|
+
input: {
|
|
50
|
+
...input,
|
|
51
|
+
authProvider: input.authProvider ?? "GOOGLE",
|
|
52
|
+
appVersion: "1.0.0",
|
|
53
|
+
platform: "WEB",
|
|
54
|
+
deviceName: "Ride Agent",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
}),
|
|
58
|
+
signal: AbortSignal.timeout(15000),
|
|
59
|
+
redirect: "error",
|
|
60
|
+
});
|
|
61
|
+
const data = (await response.json());
|
|
62
|
+
const login = data.data?.syncPrivyUser;
|
|
63
|
+
if (!response.ok ||
|
|
64
|
+
data.errors?.length ||
|
|
65
|
+
!login?.accessToken ||
|
|
66
|
+
!login.user?.id)
|
|
67
|
+
throw new AgentError("AUTH_REQUIRED", "Ride sign-in failed.", false, 401);
|
|
68
|
+
return {
|
|
69
|
+
rideAuthToken: login.accessToken,
|
|
70
|
+
identity: {
|
|
71
|
+
subject: login.user.id,
|
|
72
|
+
displayName: login.user.username ?? "Ride user",
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
const provider = new RideOAuthProvider({
|
|
77
|
+
store,
|
|
78
|
+
validateRideToken: async (token) => ({
|
|
79
|
+
subject: await validateCoreIdentity(token, graphql),
|
|
80
|
+
}),
|
|
81
|
+
exchangePrivyToken: exchange,
|
|
82
|
+
authPage: config,
|
|
83
|
+
});
|
|
84
|
+
const app = createRideHttpApp(host), resource = new URL("/mcp", base), auth = requireBearerAuth({
|
|
85
|
+
verifier: provider,
|
|
86
|
+
resourceMetadataUrl: getOAuthProtectedResourceMetadataUrl(resource),
|
|
87
|
+
}), readOnly = process.env.RIDE_PUBLIC_SUBMISSION_MODE === "true";
|
|
88
|
+
app.use(mcpAuthRouter({
|
|
89
|
+
provider,
|
|
90
|
+
issuerUrl: base,
|
|
91
|
+
baseUrl: base,
|
|
92
|
+
resourceServerUrl: resource,
|
|
93
|
+
scopesSupported: [...RIDE_OAUTH_SCOPES],
|
|
94
|
+
resourceName: "Ride",
|
|
95
|
+
}));
|
|
96
|
+
app.use(createRideOAuthApprovalRouter(provider));
|
|
97
|
+
const accountRead = (name, args, token) => invokeAccountRead(name, args, token, graphql, () => invokeAgent(backend, token, "get_portfolio", args));
|
|
98
|
+
mountAgentProxy(app, auth, backend, readOnly, accountRead);
|
|
99
|
+
if (!readOnly) {
|
|
100
|
+
mountHumanConfirmation(app, {
|
|
101
|
+
backend,
|
|
102
|
+
base: base.href,
|
|
103
|
+
cookieKey: required("RIDE_AGENT_HUMAN_COOKIE_KEY"),
|
|
104
|
+
auth: config,
|
|
105
|
+
exchange,
|
|
106
|
+
handoffs: process.env.REDIS_URL
|
|
107
|
+
? await redisHumanHandoffs(process.env.REDIS_URL)
|
|
108
|
+
: undefined,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
app.get("/health", (_req, res) => res.json({
|
|
112
|
+
service: "ride-agent-mcp",
|
|
113
|
+
version: "3",
|
|
114
|
+
release: VERSION,
|
|
115
|
+
public_submission_mode: readOnly,
|
|
116
|
+
}));
|
|
117
|
+
app.post("/mcp", auth, async (req, res) => {
|
|
118
|
+
const server = new McpServer({ name: "ride", title: "Ride Agent", version: VERSION }, { instructions: GUIDE_INSTRUCTIONS });
|
|
119
|
+
registerGuide(server);
|
|
120
|
+
registerAgentTools(server, async (name, args, extra) => {
|
|
121
|
+
if (!extra.authInfo?.scopes?.includes(mutationTools.has(name) ? "ride:trade" : "ride:read"))
|
|
122
|
+
throw new AgentError("SCOPE_REQUIRED", "Ride OAuth scope is missing.", false, 403);
|
|
123
|
+
const token = extra.authInfo?.extra?.rideAuthToken;
|
|
124
|
+
if (name === "get_portfolio" && typeof token === "string")
|
|
125
|
+
return accountRead(name, args, token);
|
|
126
|
+
return invokeAgent(backend, typeof token === "string" ? token : undefined, name, args);
|
|
127
|
+
}, readOnly, {
|
|
128
|
+
base: base.href,
|
|
129
|
+
readProposal: (id, extra) => invokeAgent(backend, extra.authInfo?.extra?.rideAuthToken, "proposal", { proposal_id: id }),
|
|
130
|
+
});
|
|
131
|
+
registerAppAccountRead(server, async (args, extra) => {
|
|
132
|
+
if (!extra.authInfo?.scopes?.includes("ride:read"))
|
|
133
|
+
throw new AgentError("SCOPE_REQUIRED", "Missing ride:read permission.", false, 403);
|
|
134
|
+
const token = extra.authInfo?.extra?.rideAuthToken;
|
|
135
|
+
if (typeof token !== "string")
|
|
136
|
+
throw new AgentError("AUTH_REQUIRED", "A Ride OAuth session is required.", false, 401);
|
|
137
|
+
return accountRead("get_my_copies", args, token);
|
|
138
|
+
});
|
|
139
|
+
const transport = new StreamableHTTPServerTransport({
|
|
140
|
+
sessionIdGenerator: undefined,
|
|
141
|
+
});
|
|
142
|
+
res.on("close", () => {
|
|
143
|
+
void transport.close();
|
|
144
|
+
void server.close();
|
|
145
|
+
});
|
|
146
|
+
try {
|
|
147
|
+
await server.connect(transport);
|
|
148
|
+
await transport.handleRequest(req, res, req.body);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
if (!res.headersSent)
|
|
152
|
+
res.status(500).json({ error: "mcp_request_failed" });
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
app.get("/mcp", (_req, res) => res.status(405).json({ error: "method_not_allowed" }));
|
|
156
|
+
app.get("/ride/guide", async (_req, res) => {
|
|
157
|
+
try {
|
|
158
|
+
res.setHeader("Cache-Control", "no-store");
|
|
159
|
+
res.json(await packagedGuide());
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
res.status(503).json({ error: "guide_unavailable" });
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
app.use(requestBodyErrorHandler);
|
|
166
|
+
app.listen(port, host, () => console.error(`Ride Agent listening on ${base.origin}/mcp`));
|
|
167
|
+
}
|
|
168
|
+
main().catch(() => {
|
|
169
|
+
console.error("Ride Agent startup failed. Check required OAuth and backend configuration.");
|
|
170
|
+
process.exitCode = 1;
|
|
171
|
+
});
|
package/dist/start.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Keep service roles intact when a platform falls back to npm start.
|
|
3
|
+
const entrypoint = process.env.RIDE_SERVICE_ENTRYPOINT ?? "server";
|
|
4
|
+
switch (entrypoint) {
|
|
5
|
+
case "server":
|
|
6
|
+
await import("./server.js");
|
|
7
|
+
break;
|
|
8
|
+
case "backend":
|
|
9
|
+
await import("./backend.js");
|
|
10
|
+
break;
|
|
11
|
+
case "bridge":
|
|
12
|
+
await import("./bridge.js");
|
|
13
|
+
break;
|
|
14
|
+
default:
|
|
15
|
+
console.error("RIDE_SERVICE_ENTRYPOINT must be server, backend or bridge.");
|
|
16
|
+
process.exitCode = 1;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
const metadata = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
3
|
+
export const VERSION = metadata.version;
|
|
4
|
+
export const PACKAGE_NAME = metadata.name;
|
|
5
|
+
// Follow the reviewed package metadata after repository transfers and renames.
|
|
6
|
+
export const GITHUB_REPOSITORY = new URL(metadata.repository.url.replace(/^git\+/, "")).pathname
|
|
7
|
+
.replace(/^\//, "")
|
|
8
|
+
.replace(/\.git$/, "");
|
|
9
|
+
export function distributionPackage(distribution) {
|
|
10
|
+
return distribution === "npm"
|
|
11
|
+
? `${PACKAGE_NAME}@${VERSION}`
|
|
12
|
+
: `github:${GITHUB_REPOSITORY}#v${VERSION}`;
|
|
13
|
+
}
|
|
14
|
+
export function mcpLaunchArgs(distribution, server) {
|
|
15
|
+
return distribution === "npm"
|
|
16
|
+
? [
|
|
17
|
+
"-y",
|
|
18
|
+
"--prefer-online",
|
|
19
|
+
`${PACKAGE_NAME}@latest`,
|
|
20
|
+
"mcp",
|
|
21
|
+
"--server",
|
|
22
|
+
server,
|
|
23
|
+
]
|
|
24
|
+
: ["-y", distributionPackage(distribution), "mcp", "--server", server];
|
|
25
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Human confirmation cards and session reuse
|
|
2
|
+
|
|
3
|
+
`show_confirmation_card` is a read-only render tool. `mode: demo` returns a
|
|
4
|
+
clearly labelled 0-USDC interface demo and never reads an account, creates a
|
|
5
|
+
financial proposal or calls the executor. `mode: proposal` reads an owned frozen
|
|
6
|
+
proposal; the backend continues to validate its owner. Recommendation and
|
|
7
|
+
preference tools keep their conversation-first outputs.
|
|
8
|
+
|
|
9
|
+
MCP Apps use the versioned `ui://ride/agent-v7-confirmation.html` resource. The
|
|
10
|
+
previous v6, v5, v4 and v3 URIs remain registered. Only the configured Ride origin is added to
|
|
11
|
+
the resource's frame policy. The card embeds `/agent/card/:proposalId`; its
|
|
12
|
+
content and human approval requests run at the Ride origin, separate from the
|
|
13
|
+
model and the MCP App sandbox. Existing confirmation, OAuth and funding pages
|
|
14
|
+
retain `DENY` / `frame-ancestors 'none'`. Only the dedicated card routes allow the
|
|
15
|
+
ChatGPT hosts, Codex's observed `codex-sandbox://*.web-sandbox.oaiusercontent.com`
|
|
16
|
+
sandbox ancestor, `https://claude.ai`, and the Claude MCP sandbox derived from
|
|
17
|
+
`sha256(<this server's canonical /mcp URL>)[:32] + .claudemcpcontent.com`.
|
|
18
|
+
The resource explicitly declares that stable origin in `_meta.ui.domain`.
|
|
19
|
+
Other Claude connectors' sandbox origins are not allowlisted. This only permits
|
|
20
|
+
framing: human endpoints still require the exact Ride origin, session, ownership
|
|
21
|
+
and CSRF checks. A normal confirmation-page link remains available as a fallback.
|
|
22
|
+
The 0-USDC demo also returns a public demo URL for hosts without MCP Apps support.
|
|
23
|
+
If the trusted frame has not reported readiness after eight seconds, the outer
|
|
24
|
+
card hides the unavailable frame and directs the user to that normal Ride page.
|
|
25
|
+
A later verified message from the exact Ride frame can restore the embedded UI.
|
|
26
|
+
This also handles Claude web's observed nested-frame block without changing CSP,
|
|
27
|
+
moving approval controls into the host sandbox or exposing session credentials.
|
|
28
|
+
|
|
29
|
+
Opening a confirmation page first restores its HttpOnly human cookie through a
|
|
30
|
+
same-origin POST. This returns only its CSRF token and original expiry, never a
|
|
31
|
+
Core JWT, and does not extend the 15-minute lifetime. If that session has expired,
|
|
32
|
+
the page tries the existing Privy session before offering Google sign-in. It
|
|
33
|
+
never initiates Google automatically. Funding pages also reuse a valid human
|
|
34
|
+
cookie while retaining the separate wallet-signing requirements.
|
|
35
|
+
|
|
36
|
+
The first embedded connection opens the normal Ride sign-in window. An existing
|
|
37
|
+
browser session is reused. That window issues a 60-second, single-use handoff
|
|
38
|
+
bound to a random challenge and proposal ID. It sends the ticket only to its
|
|
39
|
+
same-origin opener. The trusted child frame checks the popup source and origin,
|
|
40
|
+
then exchanges it for a separate HttpOnly, Secure, SameSite=None, Partitioned
|
|
41
|
+
cookie. Redis GETDEL consumes tickets atomically across gateway replicas. The
|
|
42
|
+
embedded cookie retains the original human-session expiry and is limited to
|
|
43
|
+
proposal reads, confirm and reject. It cannot grant autonomous authority or fund
|
|
44
|
+
an account. Blocked popups or unavailable partitioned storage fall back to the
|
|
45
|
+
normal Ride page; no authentication or approval checks are bypassed.
|
|
46
|
+
|
|
47
|
+
Only sanitized status/height notifications leave the trusted frame. Tokens,
|
|
48
|
+
CSRF values, handoff tickets and signing challenges never enter tool results,
|
|
49
|
+
host messages or model context. No confirm/reject/grant tool is added to MCP.
|
|
50
|
+
Preview hashes, ownership, expiry, portfolio revision and backend idempotency
|
|
51
|
+
remain authoritative. A failed or timed-out confirmation disables repeat
|
|
52
|
+
submission and offers a read of the same proposal ID.
|
|
53
|
+
|
|
54
|
+
All source changes belong to the independent Ride MCP gateway and its UI. Core,
|
|
55
|
+
GraphQL, workers, legacy App endpoints/schema, approved portfolio settings and
|
|
56
|
+
existing copy configurations are unchanged. Only the gateway needs deployment;
|
|
57
|
+
do not redeploy the bridge, backend or legacy App services for this change.
|
|
58
|
+
|
|
59
|
+
## Acceptance
|
|
60
|
+
|
|
61
|
+
Client setup must use the canonical `https://mcp.onride.me/mcp` endpoint. A legacy
|
|
62
|
+
Claude connector pointing at `https://ride-mcp-production.up.railway.app/mcp` was
|
|
63
|
+
observed as Connected with no tools on October 16, 2026. That status does not
|
|
64
|
+
prove a functioning MCP connection. Migrate the URL, complete the client's OAuth
|
|
65
|
+
flow, then verify a real tool call. Use `ride:read` for this acceptance: no trade
|
|
66
|
+
scope, real proposal creation, signing or execution is needed.
|
|
67
|
+
|
|
68
|
+
Claude and Grok Bot acceptance must distinguish authentication to the AI client,
|
|
69
|
+
Ride MCP OAuth, UI rendering, human confirmation session reuse and actual financial
|
|
70
|
+
execution. A paid-plan or trial gate is a client-access blocker, not a Ride or
|
|
71
|
+
OAuth failure. Do not start a subscription or trial on the user's behalf.
|
|
72
|
+
Protocol compatibility and local fixtures do not establish live host support.
|
|
73
|
+
|
|
74
|
+
The host bridge distinguishes incoming JSON-RPC requests from responses before
|
|
75
|
+
matching pending IDs. Host and view request IDs are independent: a host `ping`
|
|
76
|
+
using the same ID as `ui/initialize` must receive its own response without
|
|
77
|
+
completing initialization. The view answers `ping` and `ui/resource-teardown`,
|
|
78
|
+
cleans up detached frame listeners/timers, and reports its content height through
|
|
79
|
+
`ui/notifications/size-changed` after initialization and layout changes. A fixed
|
|
80
|
+
host height is respected. These protocol fixes require a fresh resource version
|
|
81
|
+
and a client tool-list refresh; they do not change human authorization.
|
|
82
|
+
|
|
83
|
+
`/fixture/protocol-host` in the loopback preview tests the real postMessage
|
|
84
|
+
protocol without an OpenAI shim. It deliberately sends a colliding ping before
|
|
85
|
+
the initialization response, delivers a zero-USDC demo, resizes its frame, and
|
|
86
|
+
provides a teardown check. No account or financial operation is available.
|
|
87
|
+
|
|
88
|
+
Claude web can also fail before any view code runs: its own
|
|
89
|
+
`/v1/toolbox/shttp/mcp/...` proxy was observed returning 405 while all matching
|
|
90
|
+
Ride requests succeeded and no Claude GET reached Ride. This matches the open
|
|
91
|
+
[Claude proxy issue](https://github.com/anthropics/claude-ai-mcp/issues/636).
|
|
92
|
+
Do not label that external failure repaired from protocol tests alone or add an
|
|
93
|
+
unauthenticated transport to work around it. Live acceptance must separately
|
|
94
|
+
check a new card, repeated page reload/resume, the normal Ride fallback and
|
|
95
|
+
session reuse on an already completed proposal, without real submission.
|
|
96
|
+
|
|
97
|
+
October 16 live acceptance: Claude web renders the outer MCP App at its stable
|
|
98
|
+
origin, but its host blocks the nested Ride frame (`chrome-error://chromewebdata/`).
|
|
99
|
+
Its official open-link flow successfully opens the public demo. Grok Bot 0.71.2
|
|
100
|
+
calls the tools and returns the fallback URL, but does not render MCP Apps in its
|
|
101
|
+
chat. Public demo confirmation and cancellation work on the production gateway.
|
|
102
|
+
These results do not establish inline financial confirmation in either client.
|
|
103
|
+
|
|
104
|
+
- Current Codex: the user expanded an existing Ride MCP card; its DOM rendered
|
|
105
|
+
the frozen proposal and clicking the parameter disclosure worked. This proves
|
|
106
|
+
card rendering and basic interaction, not the new nested confirmation flow.
|
|
107
|
+
- `npm run build`, `npm run check`, `npm test` validate the package and HTTP/MCP
|
|
108
|
+
contracts. Tests cover cookie reuse, original expiry, tamper/origin/CSRF
|
|
109
|
+
rejection, replay and embedded operation restrictions. No venue is contacted.
|
|
110
|
+
- `npx tsx scripts/confirmation-preview.ts` serves a loopback fixture. It imports
|
|
111
|
+
no venue adapter or worker. `/fixture/status` exposes login, read and mock
|
|
112
|
+
confirmation counters plus a fixed `real_orders: 0`. Browser acceptance covers
|
|
113
|
+
demo confirm/cancel, normal-page reload without another exchange, popup handoff,
|
|
114
|
+
repeated card opens without another login and mock proposal confirmation.
|
|
115
|
+
- The new gateway build must be deployed and the Ride connection refreshed
|
|
116
|
+
before calling `show_confirmation_card` in Codex. Test `mode: demo` first. A
|
|
117
|
+
successful local fixture does not prove that the current host accepts the new
|
|
118
|
+
nested frame or that real Google OAuth works inside its popup.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Ride Agent conversation flow — 2026-10-15
|
|
2
|
+
|
|
3
|
+
This revision follows Ride MCP 1015 and the user's subsequent budget-and-risk-first requirements. It retains the six fixes in `widget-account-v043.md`. Earlier V17/v0.4.2 onboarding and batch descriptions are historical; this document and the current live guide supersede those parts.
|
|
4
|
+
|
|
5
|
+
## Conversation and planning
|
|
6
|
+
|
|
7
|
+
1. Read saved preferences and ask only for missing USDC budget and risk preference (low/medium/high). Preserve partial answers in either order. A previously explicit numerical risk constraint remains a custom answer. Do not infer a budget from account balance.
|
|
8
|
+
2. Preserve explicit choices; otherwise disclose unrestricted Crypto/RWA, no symbol preset, both markets allowed and Ride-recommended copy mode. Market `both` allows results from either market independently. No initial count, market, loss percentage or execution questionnaire.
|
|
9
|
+
3. Suggest editable numerical portfolio triggers using planning preset v1 (10/20/30% for low/medium/high). Record provenance as `user`, `default`, or `recommended`. Explicit numbers override presets. Suggestions are not user consent and are not guaranteed maximum losses.
|
|
10
|
+
4. Recommend up to four feasible traders, including one. An explicit count/selection supports 1–8 and is never silently reduced. New Agent Perps plans have no 50-USDC product allocation floor and accept a 20-USDC total budget. Keep positive micro-USDC precision, risk/venue leverage caps and execution restrictions. Perps order minimums apply to the actual net opening leg after quantity rounding, with a fresh bridge check and an Agent-only Core check on rounded wire price/size before signing. Skip under-minimum entries without increasing quantity or leverage; expose the reason. Missing venue rules block increases; reduce-only dust closes keep venue exemptions. Prediction allocation rules are unchanged. Existing frozen/approved legacy plans retain their semantics.
|
|
11
|
+
5. Return `recommended_portfolio` and `candidate_table` for two compact native chat tables. The initial `candidate_page` covers the five-row table with total, timestamp and account-bound next cursor. The legacy full `candidates` array remains independent of plan failure. “Best” means prioritized within this verified source pool and constraints.
|
|
12
|
+
6. `browse_traders` sorts the complete verified snapshot by score, historical drawdown or ROI; missing metrics sort last. Page sizes are 1–20; “more 10” uses limit 10 and the same query/cursor. Compare public IDs with `compare_ids`. Unknown metric windows remain unknown and are explicitly non-comparable. Production Perps currently profiles at most the top 30 by Copy Score, plus enabled Prediction results; do not call this all market traders.
|
|
13
|
+
7. `trader_ids` pins the user's selected IDs, mapping one to single and multiple to basket. Preference edits preserve the selection and valid customized amounts/caps/exits. Explain conflicts without substituting traders or resetting allocations. `selection: system` explicitly clears the pin. Paging/sorting/comparison never replace the saved plan. No one-free-change quota remains; old batch inputs are retained only for compatibility.
|
|
14
|
+
8. Patch preferences and allocation settings progressively. Recalculation preserves omitted settings and creates a new immutable preview. Show amount, allocation, unallocated budget, copy mode, leverage caps and portfolio/sleeve exit rules. Then verify per-market funds and create a frozen proposal for human Ride confirmation. No funds or trades are authorized by the preview.
|
|
15
|
+
|
|
16
|
+
## Presentation and compatibility
|
|
17
|
+
|
|
18
|
+
Discovery, preference and account tools no longer force a Widget. Their normal surface is AI conversation and small tables. Financial proposals retain the Ride review resource. The manually opened Widget offers a compact two-answer fallback; it no longer exposes a fourteen-field onboarding form or batch quota controls.
|
|
19
|
+
|
|
20
|
+
The Skill, hosted guide, MCP tool descriptions and CLI use the same flow. `ride traders --sort drawdown --limit 10` and `ride traders --json '{"compare_ids":["PUBLIC_ID_A","PUBLIC_ID_B"]}'` use the same contracts. Existing tool arguments remain accepted; recalculate preferences/allocations can now be partial. State additions are optional JSON fields within the independent Agent table. No legacy App service, schema, account binding, approved portfolio or runner policy is changed.
|
|
21
|
+
|
|
22
|
+
Unrestricted assets, raw OK removal, full per-market account balances, candidate visibility on failed plans, 1/2/3/4 plans and actionable diagnostics remain covered. Meme account coverage and historical loss correlation remain unavailable rather than zero. New Perps Ride-recommended plans follow verified source leverage with no extra user cap by default and an optional App-style editable 1–40x cap. Explicit caps are independent of the recommendation; execution uses the minimum of source leverage, approved user cap and fresh per-asset venue limit. Existing approved caps are preserved until explicitly changed and confirmed. Budget/margin/loss/entry/minimum-order checks remain active. No extra user cap is represented by `leverage_cap: null`, rather than an arbitrary large number; proportional sizing is separate.
|
|
23
|
+
|
|
24
|
+
## Acceptance and release boundary
|
|
25
|
+
|
|
26
|
+
Tests cover partial onboarding, provenance and explicit overrides, automatic 1–4 plans, exact manual counts, paging without duplicates, whole-snapshot sorting, comparisons, cursor ownership/expiry, selected allocation preservation, conditional Fixed settings and proposal-only execution. The shared execution/accounting fixture explicitly requests six traders to keep legacy receipts comparable; new automatic-count scenarios run separately.
|
|
27
|
+
|
|
28
|
+
`npm run check`, the full suite with a disposable PostgreSQL database, real HTTP/MCP/OAuth/CLI functional scenarios, package install verification and local browser checks are separate evidence. The browser preview uses a clearly labelled scripted client with simulated venue/account data. It does not substitute for live AI-client or real-funds acceptance. Production deployment and npm publishing must be recorded separately; preparing version 0.5.0 does not mean it is released.
|
|
29
|
+
|
|
30
|
+
Local evidence for this revision: 136/136 tests passed with PostgreSQL enabled; 44/44 real HTTP/MCP/OAuth/CLI scenarios passed; package verification passed clean installs/setup for Codex, Claude Code and Cursor, including no-argument setup. The v0.4.3 managed Skill/client migration is covered, and customized Skills remain protected. Word PRD was rendered and visually checked on all eight pages. No real funding, signing, orders, production deployment or npm publishing was performed for this revision.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Conversational V17 implementation · 0.4.0
|
|
2
|
+
|
|
3
|
+
Historical release reference. Budget/risk-first onboarding and candidate browsing now follow [conversation-v050.md](conversation-v050.md); old upfront-field and batch-quota rules below are superseded.
|
|
4
|
+
|
|
5
|
+
The supplied HTML is a simulated reference. Production uses the same exploration, preview, funding and review sequence inside the MCP card resource. The host owns the conversation sidebar/composer; Ride owns tool data and cards. The original reference file is preserved.
|
|
6
|
+
|
|
7
|
+
## Behavior
|
|
8
|
+
|
|
9
|
+
| Reference requirement | Implementation |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| Trader exploration before deposit | Primary “View traders first”; recommendations do not require balance |
|
|
12
|
+
| Resume after funding | Saved plans remain account scoped; `get_portfolio` returns the last preview when no portfolio exists; `recalculate_plan` refreshes into a new plan |
|
|
13
|
+
| Alternatives and repeated editing | Selection controls call server validation directly; a single active editor uses its own element references; old cards cannot contribute duplicate amounts |
|
|
14
|
+
| Basket/risk rules | Explicit new single plans use one trader; baskets use 2–8; the historical 50-USDC Perps allocation floor is superseded by per-order venue validation (see conversation-v050.md); Prediction retains its allocation minimum; older plans retain 3–6 unique traders, exact USDC decimals, capital weight ≤55%, Perps recommended caps 3–8× bounded by risk/venue, prediction 1×; live gross concentration ≤60% |
|
|
15
|
+
| Loss rules | New `pause_then_exit` plans pause increases at 30% by default and initiate emergency exits at 70%; legacy `exit` plans retain their original threshold. Portfolio stops can exit everyone first. No guaranteed maximum loss. |
|
|
16
|
+
| Execution | Frozen proposals and human Ride confirmation; distinct configuration/submission/partial/uncertain/settlement states |
|
|
17
|
+
| Replacement | Close/wind down and reconcile old lots, verify available funds, then confirm replacement; one per rolling seven days, old copy preserved |
|
|
18
|
+
| Historical reports | Immutable hourly/event accounting marks, deposits/withdrawals excluded; displayed daily UTC series; gaps return null period profit |
|
|
19
|
+
| Diagnosis | Same-window source fills, attributed follower fills, decisions, historical parameters, funding and execution status; no invented pairing/counterfactual profit |
|
|
20
|
+
| Notifications | Opt-in daily Ride App digest, local time/IANA timezone, durable per-day deduplication and retry, digest backlog cancelled on opt-out |
|
|
21
|
+
| Funding | Account/network/asset selection from verified provider routes, owned addresses and QR, persisted request IDs and status. Perps funding wallet receipt is separate from venue deposit; prediction bridge completion still requires available-collateral refresh |
|
|
22
|
+
| Copy setup | Separate risk tolerance and fixed/proportional settings; Fixed uses verified source fills and recorded pre-trade positions; gaps block increases |
|
|
23
|
+
| Recommendation batches | One free batch change, stored Batch 1/2, quota retained after edits, browsing keeps the edited basket |
|
|
24
|
+
| Compatibility | Shared assets/direction/holding/style flags and improving alternatives; explicit acknowledgment binds to the immutable plan; unknown historical loss correlation is unavailable |
|
|
25
|
+
| Daily return | Account-scoped local-date check-in key, offer once per day; no unsolicited host message |
|
|
26
|
+
| Charts | Persisted net-profit/account-value switch, gaps remain gaps, recorded fills retain original attribution |
|
|
27
|
+
| RWA | Official asset taxonomy and historical RWA category, exact qualified symbols, verified USDC collateral and Standard account mode, independent scoped collateral validation |
|
|
28
|
+
| Other hosts | Same twenty Agent tools, Skill and CLI; MCP App buttons use the standard `tools/call` method |
|
|
29
|
+
|
|
30
|
+
The MCP App protocol follows the [official extension overview](https://apps.extensions.modelcontextprotocol.io/api/documents/Overview.html). Cards communicate through the host; no client signing secrets or direct venue requests are embedded.
|
|
31
|
+
|
|
32
|
+
## Coverage and limits
|
|
33
|
+
|
|
34
|
+
Recording starts when the new monitor observes an owned account. Earlier periods and missing event-time configurations cannot be backfilled from current trader selection. Old receipts are not reconstructed using current settings. Prediction source fill history remains explicitly unavailable; verified follower accounting remains usable. Source/follower fills are displayed as separate evidence unless causal linkage is recorded. Diagnostics do not prove hypothetical missed returns.
|
|
35
|
+
|
|
36
|
+
Daily UTC display marks are capped at the latest 366 days, with `series_truncated` and `full_snapshot_count` disclosed. Underlying snapshots remain stored. Push readiness requires Firebase configuration and a registered Ride App device. “Delivered” in the outbox means the provider accepted the request, not that the user viewed it.
|
|
37
|
+
|
|
38
|
+
This release adds optional JSON fields and tool/API routes in the independent Agent services. New private Agent Core API/gRPC and the independent execution worker opt into scoped markets. The database guard adjusts only Agent execution tables, rejects non-Agent qualified assets and does not add an SQLx migration version, so old App binaries can restart with their existing migration registry. Legacy App GraphQL/RPC contracts, API/gRPC/worker deployments and copy tables are unchanged. Full native App regression and funded exchange/push acceptance require the corresponding live accounts/devices.
|
|
39
|
+
|
|
40
|
+
## Acceptance
|
|
41
|
+
|
|
42
|
+
Run `npm run check`, `npm test` with an isolated `RIDE_AGENT_TEST_DATABASE_URL`, `npm run test:functional` with `RIDE_AGENT_FUNCTIONAL_DATABASE_URL`, and `npm run verify:package`.
|
|
43
|
+
|
|
44
|
+
The functional harness exercises real HTTP, MCP, OAuth PKCE, CLI and PostgreSQL with simulated Core identities and venue fills. It covers zero-balance preview, expired-plan refresh, repeated edits, owner isolation, fresh confirmation, execution and accounting boundaries, histories, diagnostics and notification persistence. It does not place exchange orders.
|
|
45
|
+
|
|
46
|
+
For browser acceptance in a cloned repository, run `npm run preview:cards` and open `http://127.0.0.1:17830/preview`. The local host explicitly labels its simulated venue and exposes fixture-only funding/confirmation controls. It is bound to loopback and excluded from the distributed package. The production card HTML and actual Agent HTTP handlers are used unchanged.
|
|
47
|
+
|
|
48
|
+
Prepare the independent Agent gRPC with `RIDE_AGENT_V17_RWA_SCHEMA_ENABLED=true` and `RIDE_AGENT_RWA_ENABLED=true`, then the private Agent API with `RIDE_AGENT_INTERNAL_ONLY=true`. The API exposes only health/readiness and authenticated Agent Core operations and starts no legacy queue forwarders or Meme sync. Point only the independent Agent worker and bridge to these services. Deploy the bridge and Agent backend before the MCP gateway. Keep old App service sources and flags. Rollback to the previous source revision retains added JSON fields; the previous code preserves unknown fields when persisting state. Earlier releases do not schedule the new daily digest.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Deploying V3
|
|
2
|
+
|
|
3
|
+
The client installation is independent of server activation. Three Node services communicate with the additive private Ride Core gateway. Provision PostgreSQL and Redis, configure Privy approved origins/redirects, install the Core migrations and deploy the API/worker/scheduler changes, then deploy the public gateway and native App with matching URLs. Existing App behavior remains behind the default-off feature flags.
|
|
4
|
+
|
|
5
|
+
## Gateway
|
|
6
|
+
|
|
7
|
+
- `PUBLIC_BASE_URL`: HTTPS OAuth issuer, for example `https://mcp.onride.me`.
|
|
8
|
+
- `RIDE_GRAPHQL_URL`: Ride Core GraphQL endpoint for authenticated login and identity.
|
|
9
|
+
- `PRIVY_APP_ID`, optional `PRIVY_CLIENT_ID`: approved Privy application.
|
|
10
|
+
- `REDIS_URL`: durable hosted OAuth state; required for non-loopback issuers.
|
|
11
|
+
- `RIDE_AGENT_BACKEND_URL`: private control service URL.
|
|
12
|
+
- `RIDE_AGENT_HUMAN_COOKIE_KEY`: at least 32-byte independent cookie encryption secret.
|
|
13
|
+
- `RIDE_PUBLIC_SUBMISSION_MODE=true`: eight read tools, no machine write or browser confirmation routes.
|
|
14
|
+
Read-only CLI query routes remain available. Trading requests return `READ_ONLY`.
|
|
15
|
+
|
|
16
|
+
The native App sends its existing Core JWT directly to `/agent/human/*`. OAuth machine tokens cannot confirm, authorize or revoke. The browser human surface signs in through Privy and uses encrypted, HttpOnly, SameSite cookies plus origin checks.
|
|
17
|
+
|
|
18
|
+
## Agent service
|
|
19
|
+
|
|
20
|
+
- `RIDE_AGENT_DATABASE_URL`: separate Agent PostgreSQL database.
|
|
21
|
+
- `RIDE_AGENT_CURSOR_KEY`: at least 32 characters for user-bound update cursors.
|
|
22
|
+
- `RIDE_GRAPHQL_URL`: authenticated Core identity validation.
|
|
23
|
+
- `RIDE_AGENT_EXECUTOR_URL`, `RIDE_AGENT_EXECUTOR_TOKEN`: private bridge URL and service token.
|
|
24
|
+
- `RIDE_AGENT_PRIVATE_HTTP_HOST`: optional exact bridge hostname ending in `.railway.internal` when using Railway's encrypted private network over HTTP. Public executor connections require HTTPS.
|
|
25
|
+
- `PUBLIC_BASE_URL`: matching Ride human review base.
|
|
26
|
+
- `RIDE_AGENT_ENABLED=true`: explicit service activation.
|
|
27
|
+
- `RIDE_AGENT_READ_ONLY=true`: reject backend machine writes and human confirmation/grant operations; suspend the background trading monitor. Pair with the gateway read-only flag for initial production rollout.
|
|
28
|
+
|
|
29
|
+
State and ledger records persist in PostgreSQL; each user transition locks its row and rolls back failed confirmation. The monitor starts with the service and polls independently of MCP clients. Keep a single monitor instance per Agent database until cross-process scheduling leases are added; user transactions serialize changes, but overlapping network observations should be avoided operationally.
|
|
30
|
+
|
|
31
|
+
## Private execution bridge and Core
|
|
32
|
+
|
|
33
|
+
- `RIDE_AGENT_CORE_URL`: private Core base URL with `/internal/agent-core/:operation`.
|
|
34
|
+
- `RIDE_AGENT_CORE_SERVICE_TOKEN`: Core S2S token, at least 32 characters.
|
|
35
|
+
- `RIDE_AGENT_DATABASE_URL`: Agent database for stable outbox and opaque outcome metadata.
|
|
36
|
+
- `RIDE_AGENT_TRADER_ID_SALT`: stable, private trader-ID salt; changing it invalidates old public IDs.
|
|
37
|
+
- `RIDE_AGENT_EXECUTOR_TOKEN`: separate token used by the Agent service.
|
|
38
|
+
- `RIDE_AGENT_NETWORK=testnet|mainnet`: Perps execution network; default testnet.
|
|
39
|
+
- `RIDE_AGENT_UNIFIED_ENABLED=true`: opt in to core/USDC unified accounts on the independent bridge and Strategy worker. Default off. The worker additionally requires Agent V3 metadata; legacy Strategy validation remains Standard-only. Unified USDC is read once from spot state, subtracts verified holds for available margin, and rejects other DEX exposure/orders. Portfolio margin and unified RWA execution remain unsupported. This flag does not change the user's account mode or transfer funds.
|
|
40
|
+
- `RIDE_AGENT_PREDICTION_ENABLED=true` plus `RIDE_AGENT_POLYGON_RPC_URL`: explicit prediction activation on Polygon. Prediction has no paper-trading mode in this integration.
|
|
41
|
+
- `FCM_SERVICE_ACCOUNT_JSON_BASE64`: reuse the existing Ride Firebase service account on `agent-bridge` only. Legacy raw `FIREBASE_SERVICE_ACCOUNT_JSON` / `FCM_SERVICE_ACCOUNT_JSON` remains supported. Never ship service-account credentials to clients.
|
|
42
|
+
- `RIDE_AGENT_FCM_PROJECT_ID`: optional expected Firebase project; a mismatch fails closed. Existing Ride production uses `ride-fiamma`.
|
|
43
|
+
|
|
44
|
+
## App daily-report links (0.3.1)
|
|
45
|
+
|
|
46
|
+
FCM data preserves `type=ride_agent` and includes `event_id`, `event_kind` and, when present, `portfolio_id`. New App builds route a validated event ID to `/agent/reports/:eventId`; existing notification types retain their routes. The page reads `POST /agent/human/update` with `{ "event_id": "update_..." }` using the existing Core bearer session. OAuth MCP tokens cannot read this native endpoint. Missing and foreign reports both return 404. Reports preserve their generated snapshot, including incomplete coverage and null profit; they do not change a portfolio.
|
|
47
|
+
|
|
48
|
+
Keep Core, the existing App backend and Firebase credential source unchanged. Deploy bridge and backend before updating the public gateway. Verify each terminal deployment and the gateway release independently. A Firebase API acceptance is provider acceptance; simulator injection verifies navigation, and neither establishes physical-device delivery.
|
|
49
|
+
|
|
50
|
+
Core requires `RIDE_AGENT_CORE_ENABLED=true`, the same Core S2S token, and explicit `RIDE_AGENT_PREDICTION_ENABLED=true` for prediction execution. Set `RIDE_AGENT_NETWORK` consistently in Core and bridge; mainnet also requires Core `RIDE_AGENT_MAINNET_ENABLED=true`. The API and gRPC execution gateway must share their existing `STRATEGY_CONTROL_PLANE_SERVICE_TOKEN`; this is separate from the Node-to-Core token. Existing mainnet execution epoch controls continue to apply. Signing remains in existing workers. Apply all three additive migrations from the private implementation: execution mode/quantity, prediction ownership, and archived account reuse. Legacy mode retains its original policy caps.
|
|
51
|
+
|
|
52
|
+
Perps account preparation and prediction wallet funding occur through Ride. A combined portfolio checks each market's funds independently and performs no implicit bridge/transfer. Core ownership blocks conflicting legacy writers while Agent owns the account. Release requires complete position and pending-order reconciliation.
|
|
53
|
+
|
|
54
|
+
Initial production query deployments must also set `RIDE_AGENT_READ_ONLY=true` in Core, with mainnet and prediction execution disabled. The private Core read-only allowlist rejects account and order mutations even with a valid service token.
|
|
55
|
+
|
|
56
|
+
## Acceptance before activation
|
|
57
|
+
|
|
58
|
+
Validate OAuth from each supported host, native App proposal hash/owner/revision checks, dedicated account conflicts, unknown-submit restart recovery, partial fill and zero-fill cancellation, real funding/fee reconciliation, hedge removal and gap exits, notification delivery and rollback. Offline test success does not establish venue or deployed App acceptance. Preserve attention states for unresolved prediction redemption, ambiguous receipts and venue dust.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Perps source leverage and optional user cap
|
|
2
|
+
|
|
3
|
+
New Agent Perps allocations use `leverage_mode: "follow_source"` and
|
|
4
|
+
`leverage_cap: null`: there is no extra user cap by default. Numeric settings
|
|
5
|
+
use `custom_cap`, editable from 1–40x like App Auto-Ride. Explicit `null` clears
|
|
6
|
+
the cap; omitted fields preserve it. Prediction remains at 1x.
|
|
7
|
+
|
|
8
|
+
Actual leverage is the minimum of verified source leverage, the optional user
|
|
9
|
+
cap and fresh per-asset exchange metadata. Missing source/venue evidence blocks
|
|
10
|
+
increases. Changed venue rules invalidate sizing even without a source trade;
|
|
11
|
+
the bridge rejects an increase if its frozen leverage no longer fits fresh
|
|
12
|
+
rules. Budget, gross margin, loss triggers, entry deviation and opening-order
|
|
13
|
+
minimum checks remain in place. Under-minimum orders are skipped without
|
|
14
|
+
increasing quantity or leverage.
|
|
15
|
+
|
|
16
|
+
Old approved allocations with no `leverage_mode` retain their numeric caps and
|
|
17
|
+
old validation. Changing or clearing a running cap creates a new frozen human
|
|
18
|
+
confirmation proposal. A delegation with a numeric cap never silently approves
|
|
19
|
+
a no-cap plan.
|
|
20
|
+
|
|
21
|
+
## Isolated rollout
|
|
22
|
+
|
|
23
|
+
Deploy only the independent Core gRPC, Core API and Core execution services
|
|
24
|
+
first. Their rollout preserves existing approved settings. Verify the gRPC
|
|
25
|
+
schema preflight and all three services before applying bridge/backend changes;
|
|
26
|
+
publish the MCP gateway last. Keep old App API/worker/gRPC services
|
|
27
|
+
on their current deployments. Publish the backend's nullable input support
|
|
28
|
+
before exposing the new gateway tool schemas. No real plan activation or order
|
|
29
|
+
is needed for acceptance.
|
|
30
|
+
|
|
31
|
+
The opt-in Core bootstrap preserves old policy records, existing numeric
|
|
32
|
+
precision, column-level immutable triggers, long-lived prepared statements,
|
|
33
|
+
the current-policy view identity/permissions and the SQLx migration registry.
|
|
34
|
+
Only execution checks expand within the existing NUMERIC(8,4) range; the
|
|
35
|
+
existing Core 1–100 leverage wire range is not substituted for a user cap.
|
|
36
|
+
Legacy bindings retain their 100% exposure checks. Use the independent gRPC
|
|
37
|
+
pre-deploy command `RIDE_AGENT_SCHEMA_PREFLIGHT_ONLY=true ./grpc` so schema
|
|
38
|
+
validation completes before replacing the running instance. Exchange limits
|
|
39
|
+
and the approved policy are still checked on execution.
|
|
40
|
+
|
|
41
|
+
Acceptance uses a disposable PostgreSQL database and simulated exchanges:
|
|
42
|
+
20-USDC plans, 10-USDC sleeves, optional 20x/40x caps, clearing caps, verified
|
|
43
|
+
source/venue limits above 40x, legacy 3x preservation and minimum-order skips.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Prediction historical risk metrics
|
|
2
|
+
|
|
3
|
+
Prediction candidates previously returned null historical ROI/drawdown. The first repair added a native economic-PnL path, but many upstream points carry old observations and some wallets lack a complete lifetime funding ledger. Those remain unavailable in that path; the checks are not relaxed.
|
|
4
|
+
|
|
5
|
+
## Reconstruct historical equity independently
|
|
6
|
+
|
|
7
|
+
The Agent bridge can now reconstruct a one-month daily inventory curve from the configured Polygon RPC and official Polymarket prices:
|
|
8
|
+
|
|
9
|
+
1. Fix a confirmed chain block, network 137, and a common UTC daily grid covering at least 28 days.
|
|
10
|
+
2. Enumerate current OPEN and REDEEMABLE_LOST outcome inventory, plus every relevant ERC-1155 transfer in the window. Losing unredeemed positions must be included because they can have had positive historical value.
|
|
11
|
+
3. Follow both directions of `alchemy_getAssetTransfers` to explicit completion for the two collateral tokens and configured CTF contract. Retain raw integer ERC-20 and ERC-1155 amounts, token IDs, blocks and timestamps; de-duplicate self-transfers by log identity.
|
|
12
|
+
4. Read actual cash and batch outcome balances at the end block, reverse the complete transfers to each historical instant, then independently read every balance at the start block. Every reconstructed boundary balance must match exactly. Wallet activity and chain transfers cross-check financial transaction coverage. Missing activity rows for direct ERC-20 transfers or exact Safe CALL transfers are independently decoded and matched to actual token/amount/from/to evidence as external capital. Arbitrary calls and delegatecalls are not inferred; complete 1:1 USDC.e/pUSD wrap or unwrap receipt pairs are internal conversions rather than external capital; the issuer's actual vault is resolved on-chain for unwrap receipts. Other unclassified movements fail closed.
|
|
13
|
+
5. Value historical holdings from `/v2/prices-history`. A three-hour aggregate can be used only after its observation window has ended, with at most six hours of price age. Missing coarse bars can use a retained point-in-time observation from a finer tier only if the same no-future and six-hour age checks pass. When the v2 tier is missing a retained quote, a bounded official CLOB archive window can supply an independently timestamped mark, with the same age/no-future checks and a conservatively treated one-hour sampling interval. Out-of-window terminal points are discarded. Fallback sources are disclosed. No interpolation or unlimited carry-forward is allowed. The current anchor additionally uses a point-in-time price read, preserving the 1% reconciliation limit rather than widening it to accommodate a three-hour average. Actual CTF payout numerators/denominators determine settlement prices. The payout slot is derived by matching the actual token ID against CTF collection IDs and on-chain collateral identities; external outcome labels and CLOB indices are not assumed to be payout indices. Resolution block or transaction hints accelerate the lookup only after archive reads prove the zero-to-nonzero payout transition; otherwise binary search locates the first settled block, so current settlement cannot be applied to earlier holdings.
|
|
14
|
+
6. Compare current marked equity with the independent official accounting snapshot, retaining the existing maximum 1% discrepancy rule and its exact disclosed value. Recheck the anchor block hash to reject reorgs.
|
|
15
|
+
|
|
16
|
+
`E = cash + sum(outcome quantity * observed price)`. Link unit NAV using `(E[i] + interval withdrawals) / (E[i-1] + interval deposits)`; maximum peak-to-trough unit-NAV decline is drawdown, and cumulative unit-NAV change is ROI. Current and historical balances include actual trading fees, redemptions and wallet income without needing missing PnL atoms or a lifetime initial-deposit event. The complete activity feed identifies external deposits/withdrawals and tips for capital-flow adjustment. All arithmetic uses integer raw token units and Decimal.
|
|
17
|
+
|
|
18
|
+
The results remain **daily sampled, cashflow-adjusted estimated account performance**, with explicit window, basis, three-hour mark resolution, maximum mark age, block range/hash, transfer/token counts and reconciliation difference. They are not all-time/intraday maximum drawdown, follower results, or a future loss bound. Sampling and interval cashflow timing can miss losses within a day. The supported reconstruction scope is the configured v1 CTF contract and two collateral tokens; unsupported token modules, missing prices, incomplete pagination or unclassified transfers remain unavailable with a reason.
|
|
19
|
+
|
|
20
|
+
## Availability and compatibility
|
|
21
|
+
|
|
22
|
+
Reconstruction runs outside recommendation latency, at most two wallet jobs and six external HTTP requests at a time, with read-only RPC calls batched in groups of at most twenty and a bounded shared historical-price cache, with a five-minute deadline per wallet. Verified metrics and curve evidence are persisted in the private Agent `ride_agent_prediction_history` cache under opaque trader IDs. A one-hour background refresh retains an earlier verified result only within the existing 36-hour history freshness window. Fresh records survive process restarts. While reconstruction is pending, the original validated PnL path remains available; missing evidence never becomes zero. Scores remain discoverable independently of history availability. No legacy App table, API, approved plan or execution path is changed.
|
|
23
|
+
|
|
24
|
+
The source contracts are the official [Polymarket v2 Data API](https://data-api.polymarket.com/v2/docs), the official SDK's [accounting snapshot route](https://github.com/Polymarket/py-sdk/blob/main/src/polymarket/_internal/actions/data.py), and [Alchemy's Transfers API](https://www.alchemy.com/docs/data/transfers-api/transfers-endpoints/alchemy-get-asset-transfers).
|
|
25
|
+
|
|
26
|
+
New recommendations also penalize partially shared topic/asset sets using intersection over union. Exact asset matches keep their existing penalty; style, direction and market penalties remain. This improves topic diversity without fabricating measured loss correlation or changing existing saved portfolios.
|
|
27
|
+
|
|
28
|
+
The configured portfolio loss trigger, Prediction 1x cap, 50 USDC per-trader minimum, live execution preflight and final human confirmation remain in force.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Preferences and trading-account funding · 0.4.2
|
|
2
|
+
|
|
3
|
+
Historical release reference. Budget/risk-first onboarding and candidate browsing now follow [conversation-v050.md](conversation-v050.md); old upfront-field and batch-quota rules below are superseded.
|
|
4
|
+
|
|
5
|
+
Recommendations return structured missing questions before reading candidates. `get_preferences` reads saved/partial answers; `set_preferences` merges supplied answers and returns remaining questions. Budget, acceptable loss and market are required; explicit basket/Fixed choices require their size/entry amount. Existing answers and portfolios are retained; older saved previews also restore preferences when their separate preference record was empty. The card starts with empty budget/loss and an unselected market. AI instructions forbid invented values.
|
|
6
|
+
|
|
7
|
+
`get_deposit_address` and `check_deposit_status` distinguish receiving-wallet USDC from verified trading collateral. `prepare_deposit` freezes an exact amount and owned account, returns a human confirmation URL, and moves no funds. The browser can review a changed amount, then separately confirm funding and any required account activation. Embedded owners sign the existing Core Permit/approveAgent challenges; server-master owners explicitly confirm the existing Core relayer operation. Signatures/challenges are absent from MCP output. All confirmation requests use authenticated Core identity and browser CSRF; no machine confirmation tool is registered.
|
|
8
|
+
|
|
9
|
+
The funding identity is durably consumed before external submission. Concurrent confirmations submit once; uncertain results block new funding requests. Credit requires the matching native-USDC Transfer log to the fixed Arbitrum bridge and observed trading available balance; wallet credit alone is insufficient. Verified trading balance and sufficient funds for the saved plan are reported separately. Prediction status also reads verified trading collateral instead of treating provider completion as ready.
|
|
10
|
+
|
|
11
|
+
The isolated Core API opts in with `RIDE_AGENT_FUNDING_ENABLED=true` and `RIDE_AGENT_INTERNAL_ONLY=true`. Its adapter reuses existing funding, wallet-generation, signature-verification and writer-lease capabilities. Other API deployments cannot use this route. Only the isolated API receives references to existing relayer/Privy credentials; automatic deposit/close workers stay disabled. No old App binary, GraphQL/RPC contract, table migration or service deployment is changed.
|
|
12
|
+
|
|
13
|
+
Acceptance before deployment: 105 TypeScript/PostgreSQL checks; 38 HTTP/MCP/OAuth/CLI/Pg scenarios using simulated identities and transactions; two Core read-only/epoch checks. Browser fixture verified missing-preference gating and funding confirmation through observed trading balance. Fixtures do not establish a real financial transaction. The signed-in Glen account is reserved for human-confirmed production acceptance.
|
|
14
|
+
|
|
15
|
+
Production acceptance on 2026-10-13: the isolated Core API (`b4afbcf`) and all three MCP services (`ac18f8d`) reached Railway SUCCESS. The public health endpoint reports 0.4.2; authenticated MCP lists 24 tools and serves the updated workflow. Existing preferences and pre-upgrade deposit tickets remain readable. The quote-only preflight reaches the live Core adapter and rejects insufficient receiving-wallet funds without a submission. Trading readiness and saved-plan funding are reported independently. Production browser authentication succeeds; App copy reads have complete coverage, and the old App API readiness/GraphQL probes succeed. Acceptance excludes money movement, so real transfer, wallet signature and trading credit remain unverified. Private account evidence stays outside the distributed package.
|
|
16
|
+
|
|
17
|
+
Limits: transfers still require the user's confirmation/signature. Unknown broadcasts require reconciliation, not another submission. Existing account ownership fences remain enforced. Funding to the Core Perps scope does not automatically move collateral into an RWA DEX scope. Physical App push/release remains separate.
|