Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
4b6fabb
Merge pull request #114 from MemTensor/main
Wang-Daoji Jul 30, 2026
fbdaac2
feat: exclude dependency tests and docs from desktop packages (#123)
wustzdy Jul 31, 2026
e5734d5
Merge pull request #124 from MemTensor/main
Wang-Daoji Jul 31, 2026
302b8cd
fix: unify cross-agent action backgrounds
Jul 31, 2026
d692f00
Merge pull request #125 from hijzy/main
hijzy Jul 31, 2026
f108ad4
fix: simplify memory tool call headings
Jul 31, 2026
33729a2
Merge pull request #126 from hijzy/main
hijzy Jul 31, 2026
6642966
feat(memory): commit episode routing on turn complete
Aug 3, 2026
328c5df
Merge pull request #130 from hijzy/main
hijzy Aug 3, 2026
b7129d7
fix(memory): separate retrieval content and validate L3 evidence
Aug 3, 2026
8377766
Merge pull request #131 from hijzy/main
hijzy Aug 3, 2026
3074213
fix(memory): finalize episode rewards and processing
Aug 3, 2026
54b3dfe
Merge pull request #132 from hijzy/main
hijzy Aug 3, 2026
9407529
chore: docs
Aug 3, 2026
f8cf955
chore: readme
Aug 3, 2026
64ceb34
Merge pull request #133 from hijzy/main
hijzy Aug 3, 2026
b0b4df2
chore: show invitation token (#135)
ZongYue99 Aug 3, 2026
c388e5d
feat(memory): link related memory details
Aug 3, 2026
4ee0775
Merge pull request #136 from hijzy/main
hijzy Aug 3, 2026
9857a05
feat(analytics): track desktop memory adds during agent-source scans …
antalike Aug 3, 2026
ca31449
feat: merge pkg && optimize pkg (#140)
wustzdy Aug 3, 2026
91e881d
feat: tighten onboarding activation with cross-agent relay and produc…
Aug 3, 2026
49ea071
fix(backend): share scan permission per installation
Aug 3, 2026
06d7ae2
chore: reorganize desktop packaging internal scripts (#141)
wustzdy Aug 3, 2026
627bbb3
Merge pull request #142 from hijzy/main
hijzy Aug 3, 2026
2f59808
fix(backend): refine onboarding permissions and actions
Aug 4, 2026
65bf870
Merge pull request #143 from hijzy/main
hijzy Aug 4, 2026
326d7b9
fix: surface structured quota exhaustion errors
Wang-Daoji Aug 4, 2026
8b317cf
Merge pull request #144 from Wang-Daoji/feature/v1.0.5-wy
Wang-Daoji Aug 4, 2026
f58510c
feat(memory): add time-filtered trace recall
Aug 4, 2026
03499e9
Merge pull request #145 from hijzy/main
hijzy Aug 4, 2026
3e8ce6d
feat: trust Codex hooks and reveal account identifiers
Aug 4, 2026
43127e9
Merge pull request #146 from hijzy/main
hijzy Aug 4, 2026
becb87e
fix(config): fail loud on invalid config instead of silently using de…
fancyboi999 Aug 4, 2026
8656996
feat(feishu): add QR bot setup (#127)
Ericwong5021 Aug 4, 2026
80b07d7
fix(memmy-memory): surface memory-service outages instead of silent f…
fancyboi999 Aug 4, 2026
b826c35
chore: add embedding mode into pkg (#147)
wustzdy Aug 4, 2026
8c778ed
feat(analytics): send userId at the top level of /api/analytics/event…
antalike Aug 4, 2026
03783f4
feat: refine product tour for deny-scan and scroll placement
Aug 4, 2026
b394e9e
fix(memory): keep short pattern terms out of raw JSON metadata columns
DevMello Aug 4, 2026
163fdf8
fix(backend): stop capturing tool results as the user query
DevMello Aug 5, 2026
bae7941
feat: reshape onboarding analytics for funnel-friendly step tracking
Aug 5, 2026
5721f0f
Merge pull request #1 from antalike/feat/onboarding-activation
dolnna Aug 5, 2026
19c1a80
fix(settings): show BYOK usage detail copy (#155)
syzsunshine219 Aug 5, 2026
ef31740
fix: seed first-report chat instead of re-running the agent
Aug 5, 2026
23aa28d
Merge pull request #157 from dolnna/feat/onboarding-activation
hijzy Aug 5, 2026
c35fa1b
Merge pull request #2 from antalike/feat/onboarding-activation
dolnna Aug 5, 2026
38f5de3
Merge pull request #158 from dolnna/feat/onboarding-activation
hijzy Aug 5, 2026
6b76ae4
feat(onboarding): focus initial report on preferences and latest task
Aug 5, 2026
3304626
Merge remote-tracking branch 'upstream/dev-onboarding'
Aug 5, 2026
1190afc
feat(onboarding): prioritize first report memory handoff
Aug 5, 2026
9622626
fix(onboarding): preserve first report context across agents
Aug 5, 2026
8cd4d71
fix(onboarding): streamline first report handoff
Aug 5, 2026
9922a4f
fix(desktop): store Windows packaged data under install dir (#165)
wustzdy Aug 6, 2026
c0ae357
feat(timezone): honor user UTC offsets across memory
hijzy Aug 6, 2026
a148ed1
Merge pull request #166 from hijzy/main
hijzy Aug 6, 2026
fb9da37
feat: add Pi and QwenWork memory sources
hijzy Aug 6, 2026
b9eb8cc
Merge pull request #167 from hijzy/main
hijzy Aug 6, 2026
8a52a03
fix: rename qwenwork display label
hijzy Aug 6, 2026
2c53f05
Merge pull request #168 from hijzy/main
hijzy Aug 6, 2026
c5833ee
feat: add preset Agent selector
hijzy Aug 6, 2026
e3424ee
Merge pull request #169 from hijzy/main
hijzy Aug 6, 2026
1fcbba4
memmy-agent: Let every AI remember the same you - V1.0.5 (#173)
ZongYue99 Aug 6, 2026
5bb98ea
fix(desktop): keep conversation composer growing and scrollable (#171)
antalike Aug 6, 2026
4aae59d
fix(memory): show quota error title for 40309
hijzy Aug 6, 2026
90b062a
Merge pull request #175 from hijzy/main
hijzy Aug 6, 2026
1538e74
fix(memory): harden cross-agent onboarding
hijzy Aug 7, 2026
ba13bad
Merge pull request #177 from hijzy/main
hijzy Aug 7, 2026
fdc6d05
fix(memory): hide unverified agent drafts
hijzy Aug 7, 2026
cbc97db
Merge pull request #178 from hijzy/main
hijzy Aug 7, 2026
95f423a
chore(release): publish Memmy v1.0.5 (#174)
syzsunshine219 Aug 6, 2026
91f0566
merge: record upstream/main as integrated into v1.0.6
Wang-Daoji Aug 7, 2026
091182b
Merge pull request #179 from Wang-Daoji/codex/sync-main-into-v1.0.6
Wang-Daoji Aug 7, 2026
12c9dae
fix(desktop): mask account identifiers
hijzy Aug 10, 2026
6f9eba6
Merge pull request #184 from hijzy/main
hijzy Aug 10, 2026
4cc22b0
fix(backend): quote hook commands for Windows shells (#153)
DevMello Aug 10, 2026
32e09d2
fix(openai-api): report turn token usage (#181)
fancyboi999 Aug 10, 2026
34e899c
fix(desktop): set microphone usage description by package edition (#185)
antalike Aug 10, 2026
d6a7f78
feat: Enhance error handling and metadata propagation for model error…
EF1874 Aug 10, 2026
a861f2a
Merge pull request #152 from DevMello/fix/pattern-terms-json-noise
hijzy Aug 10, 2026
431d57b
Merge pull request #154 from DevMello/fix/hook-stop-capture-query
hijzy Aug 10, 2026
610c3c4
feat(scripts): add Windows clear-all utility (#190)
syzsunshine219 Aug 11, 2026
29a1eeb
feat(analytics): track tools and connections outcomes to cloud GA4 (#…
antalike Aug 11, 2026
70b12a8
polish readme (#194)
ZongYue99 Aug 11, 2026
2e2a1ef
feat: add startup splash localization and HTML rendering (#193)
EF1874 Aug 11, 2026
5776476
fix(settings): show Windows status bar copy (#192)
syzsunshine219 Aug 11, 2026
248e997
fix(onboarding): hide first-report wrapper tags (#196)
syzsunshine219 Aug 11, 2026
dd7c2ac
fix(settings): default intl language selector to English (#195)
syzsunshine219 Aug 11, 2026
c445f32
polish readme (#197)
ZongYue99 Aug 11, 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
7 changes: 5 additions & 2 deletions App/backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ npm run db:migrate
- `adapters/inbound/local-api`: Fastify routes, runtime-token authentication,
CORS, SSE, and the Composio MCP bridge.
- `adapters/outbound/agent-source`: built-in history readers for Cursor, Claude
Code, Codex, OpenCode, OpenClaw, Hermes, and WorkBuddy.
Code, Codex, OpenCode, OpenClaw, Hermes, WorkBuddy, Pi, and qwenwork.
- `adapters/outbound/skill-writer`: Memory skill, hook, command, and plugin
installation for the supported agents.
- `adapters/outbound/agent-adapter`: manifest, loader, and registry contracts
Expand Down Expand Up @@ -118,10 +118,13 @@ Every route in this table requires the local runtime token.
| OpenClaw | SQLite databases under `~/.openclaw/` | Workspace `AGENTS.md`, `~/.openclaw/skills/memmy-memory/`, and the Memory extension |
| Hermes | `~/.hermes/sessions/**/*.jsonl` and `~/.hermes/state.db` | `~/.hermes/SOUL.md`, `skills/memmy-memory/`, and Memory/resume plugins |
| WorkBuddy | `~/.workbuddy/projects/**/*.jsonl` | `~/.workbuddy/skills/memmy-memory/` |
| Pi | `~/.pi/agent/sessions/**/*.jsonl` | `~/.pi/agent/skills/memmy-memory/` |
| qwenwork | `~/.qwenworkcn/projects/**/*.jsonl` | `~/.qwenworkcn/skills/memmy-memory/` |

Agent roots can be overridden with `CLAUDE_CONFIG_DIR`, `CODEX_HOME`,
`OPENCODE_CONFIG_DIR`, `OPENCLAW_STATE_DIR`, `HERMES_HOME`,
`WORKBUDDY_CONFIG_DIR`, or `CODEBUDDY_CONFIG_DIR`, as applicable.
`WORKBUDDY_CONFIG_DIR`, `CODEBUDDY_CONFIG_DIR`, `PI_CODING_AGENT_DIR`, or
`QWENWORK_CONFIG_DIR`, as applicable.

## Memory Layer Configuration

Expand Down
15 changes: 15 additions & 0 deletions App/backend/local-api-contracts/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ export type MemoryServiceRuntimeConfig = z.infer<typeof MemoryServiceRuntimeConf
export const RuntimeConfigSchema = z.object({
baseUrl: z.string().url(),
localToken: z.string().min(1),
timeZone: z.string().min(1).optional(),
memory: MemoryServiceRuntimeConfigSchema.optional(),
agentGateway: AgentGatewayRuntimeConfigSchema.optional()
});
Expand Down Expand Up @@ -1057,6 +1058,20 @@ export const IntegrationConnectionsResponseSchema = z.object({
});
export type IntegrationConnectionsResponse = z.infer<typeof IntegrationConnectionsResponseSchema>;

/**
* Schema for UI-reported tool connection outcomes (integration OAuth end-state,
* channel QR/start abandon, etc.). `errorCode=cancelled` means user closed mid-flow.
*/
export const ReportIntegrationConnectionEventInputSchema = z.object({
surface: z.enum(["channel", "integration"]),
toolkit: z.string().min(1),
event: z.enum(["connected", "failed"]),
errorCode: z.string().min(1).optional()
});
export type ReportIntegrationConnectionEventInput = z.infer<
typeof ReportIntegrationConnectionEventInputSchema
>;

/** Schema for execute integration tool input. */
export const ExecuteIntegrationToolInputSchema = z.object({
toolSlug: z.string().min(1),
Expand Down
1 change: 1 addition & 0 deletions App/backend/local-api-contracts/src/memory-runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export const MemoryProcessingRecordSchema = z.object({
errorCode: z.string().nullable().optional(),
errorMessage: z.string().nullable().optional(),
failedAt: IsoTimeSchema.nullable().optional(),
autoRetryScheduled: z.boolean().optional(),
updatedAt: IsoTimeSchema
});
export type MemoryProcessingRecord = z.infer<typeof MemoryProcessingRecordSchema>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { registerTurnRoutes } from "./turns.js";

export interface AgentRuntimeRouteDeps {
services: BackendServices;
timeZone?: string;
authenticateRuntimeToken: (request: FastifyRequest, reply: FastifyReply) => Promise<unknown>;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
import { z } from "zod";
import type { FastifyInstance } from "fastify";
import { withErrorEnvelope } from "../../../../../services/error-envelope.js";
import type { RuntimeContext } from "../../../../../services/runtime-context.js";
import { runtimeContextFromRequest } from "../../../../../services/runtime-context.js";
import type { AgentRuntimeRouteDeps } from "./index.js";

const MemoryParamsSchema = z.object({
Expand All @@ -21,7 +21,7 @@ export function registerMemoryRoutes(app: FastifyInstance, deps: AgentRuntimeRou
{ preHandler: deps.authenticateRuntimeToken },
withErrorEnvelope(async (request, reply) => {
const input = AddMemoryInputSchema.parse(request.body);
return reply.send(await deps.services.memoryDetail.add(input, runtimeContext()));
return reply.send(await deps.services.memoryDetail.add(input, runtimeContextFromRequest(request, deps.timeZone)));
})
);

Expand All @@ -39,7 +39,7 @@ export function registerMemoryRoutes(app: FastifyInstance, deps: AgentRuntimeRou
tools,
excludedSourceAgents
});
return reply.send(await deps.services.panel.memoryApiLogs(input, runtimeContext()));
return reply.send(await deps.services.panel.memoryApiLogs(input, runtimeContextFromRequest(request, deps.timeZone)));
})
);

Expand Down Expand Up @@ -70,7 +70,7 @@ export function registerMemoryRoutes(app: FastifyInstance, deps: AgentRuntimeRou
{ preHandler: deps.authenticateRuntimeToken },
withErrorEnvelope(async (request, reply) => {
const params = MemoryParamsSchema.parse(request.params);
return reply.send(await deps.services.memoryDetail.getById(params.id, runtimeContext()));
return reply.send(await deps.services.memoryDetail.getById(params.id, runtimeContextFromRequest(request, deps.timeZone)));
})
);

Expand All @@ -80,15 +80,11 @@ export function registerMemoryRoutes(app: FastifyInstance, deps: AgentRuntimeRou
withErrorEnvelope(async (request, reply) => {
const params = MemoryParamsSchema.parse(request.params);
const input = DeleteMemoryInputSchema.parse(request.body ?? {});
return reply.send(await deps.services.memoryDetail.delete(params.id, input, runtimeContext()));
return reply.send(await deps.services.memoryDetail.delete(params.id, input, runtimeContextFromRequest(request, deps.timeZone)));
})
);
}

function runtimeContext(): RuntimeContext {
return { adapterId: "runtime" };
}

function queryValues(rawUrl: string | undefined, name: string): string[] | undefined {
const values = new URL(rawUrl ?? "/", "http://localhost").searchParams
.getAll(name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@ import { PanelItemsInputSchema, PanelTasksInputSchema } from "@memmy/local-api-c
import type { FastifyInstance } from "fastify";
import { z } from "zod";
import { withErrorEnvelope } from "../../../../../services/error-envelope.js";
import type { RuntimeContext } from "../../../../../services/runtime-context.js";
import { runtimeContextFromRequest } from "../../../../../services/runtime-context.js";
import type { AgentRuntimeRouteDeps } from "./index.js";

export function registerPanelRoutes(app: FastifyInstance, deps: AgentRuntimeRouteDeps): void {
app.get(
"/api/v1/panel/overview",
{ preHandler: deps.authenticateRuntimeToken },
withErrorEnvelope(async (_request, reply) => {
return reply.send(await deps.services.panel.overview(runtimeContext()));
withErrorEnvelope(async (request, reply) => {
return reply.send(await deps.services.panel.overview(runtimeContextFromRequest(request, deps.timeZone)));
})
);

app.get(
"/api/v1/panel/analysis",
{ preHandler: deps.authenticateRuntimeToken },
withErrorEnvelope(async (_request, reply) => {
return reply.send(await deps.services.panel.analysis(runtimeContext()));
withErrorEnvelope(async (request, reply) => {
return reply.send(await deps.services.panel.analysis(runtimeContextFromRequest(request, deps.timeZone)));
})
);

Expand All @@ -33,7 +33,7 @@ export function registerPanelRoutes(app: FastifyInstance, deps: AgentRuntimeRout
...rawQuery,
excludedSourceAgents
});
return reply.send(await deps.services.panel.items(input, runtimeContext()));
return reply.send(await deps.services.panel.items(input, runtimeContextFromRequest(request, deps.timeZone)));
})
);

Expand All @@ -42,7 +42,7 @@ export function registerPanelRoutes(app: FastifyInstance, deps: AgentRuntimeRout
{ preHandler: deps.authenticateRuntimeToken },
withErrorEnvelope(async (request, reply) => {
const input = PanelTasksInputSchema.parse(request.query);
return reply.send(await deps.services.panel.tasks(input, runtimeContext()));
return reply.send(await deps.services.panel.tasks(input, runtimeContextFromRequest(request, deps.timeZone)));
})
);

Expand All @@ -51,16 +51,12 @@ export function registerPanelRoutes(app: FastifyInstance, deps: AgentRuntimeRout
{ preHandler: deps.authenticateRuntimeToken },
withErrorEnvelope(async (request, reply) => {
const { id } = z.object({ id: z.string().min(1) }).parse(request.params);
return reply.send(await deps.services.panel.deleteTask(id, runtimeContext()));
return reply.send(await deps.services.panel.deleteTask(id, runtimeContextFromRequest(request, deps.timeZone)));
})
);

}

function runtimeContext(): RuntimeContext {
return { adapterId: "runtime" };
}

function queryValues(rawUrl: string | undefined, name: string): string[] | undefined {
const values = new URL(rawUrl ?? "/", "http://localhost").searchParams
.getAll(name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { SearchInputSchema } from "@memmy/local-api-contracts";
import type { FastifyInstance } from "fastify";
import { withErrorEnvelope } from "../../../../../services/error-envelope.js";
import type { RuntimeContext } from "../../../../../services/runtime-context.js";
import { runtimeContextFromRequest } from "../../../../../services/runtime-context.js";
import type { AgentRuntimeRouteDeps } from "./index.js";

export function registerSearchRoute(app: FastifyInstance, deps: AgentRuntimeRouteDeps): void {
Expand All @@ -11,8 +11,7 @@ export function registerSearchRoute(app: FastifyInstance, deps: AgentRuntimeRout
{ preHandler: deps.authenticateRuntimeToken },
withErrorEnvelope(async (request, reply) => {
const input = SearchInputSchema.parse(request.body);
const ctx: RuntimeContext = { adapterId: "runtime" };
return reply.send(await deps.services.search.search(input, ctx));
return reply.send(await deps.services.search.search(input, runtimeContextFromRequest(request, deps.timeZone)));
})
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
import { z } from "zod";
import type { FastifyInstance } from "fastify";
import { withErrorEnvelope } from "../../../../../services/error-envelope.js";
import type { RuntimeContext } from "../../../../../services/runtime-context.js";
import { runtimeContextFromRequest } from "../../../../../services/runtime-context.js";
import type { AgentRuntimeRouteDeps } from "./index.js";

const SessionParamsSchema = z.object({
Expand All @@ -19,7 +19,7 @@ export function registerSessionRoutes(app: FastifyInstance, deps: AgentRuntimeRo
{ preHandler: deps.authenticateRuntimeToken },
withErrorEnvelope(async (request, reply) => {
const input = OpenSessionInputSchema.parse(request.body ?? {});
const result = await deps.services.session.open(input, runtimeContext());
const result = await deps.services.session.open(input, runtimeContextFromRequest(request, deps.timeZone));
return reply.send(result.response);
})
);
Expand All @@ -30,13 +30,9 @@ export function registerSessionRoutes(app: FastifyInstance, deps: AgentRuntimeRo
withErrorEnvelope(async (request, reply) => {
const params = SessionParamsSchema.parse(request.params);
const input = CloseSessionInputSchema.parse(request.body ?? {});
const result = await deps.services.session.close(params.sessionId, input, runtimeContext());
const result = await deps.services.session.close(params.sessionId, input, runtimeContextFromRequest(request, deps.timeZone));
return reply.send(result.response);
})
);

}

function runtimeContext(): RuntimeContext {
return { adapterId: "runtime" };
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { CompleteTurnInputSchema, StartTurnInputSchema } from "@memmy/local-api-
import { z } from "zod";
import type { FastifyInstance } from "fastify";
import { withErrorEnvelope } from "../../../../../services/error-envelope.js";
import type { RuntimeContext } from "../../../../../services/runtime-context.js";
import { runtimeContextFromRequest } from "../../../../../services/runtime-context.js";
import type { AgentRuntimeRouteDeps } from "./index.js";

const TurnParamsSchema = z.object({
Expand All @@ -16,7 +16,7 @@ export function registerTurnRoutes(app: FastifyInstance, deps: AgentRuntimeRoute
{ preHandler: deps.authenticateRuntimeToken },
withErrorEnvelope(async (request, reply) => {
const input = StartTurnInputSchema.parse(request.body);
return reply.send(await deps.services.turn.start(input, runtimeContext()));
return reply.send(await deps.services.turn.start(input, runtimeContextFromRequest(request, deps.timeZone)));
})
);

Expand All @@ -26,12 +26,8 @@ export function registerTurnRoutes(app: FastifyInstance, deps: AgentRuntimeRoute
withErrorEnvelope(async (request, reply) => {
const params = TurnParamsSchema.parse(request.params);
const input = CompleteTurnInputSchema.parse(request.body);
const result = await deps.services.turn.complete(params.turnId, input, runtimeContext());
const result = await deps.services.turn.complete(params.turnId, input, runtimeContextFromRequest(request, deps.timeZone));
return reply.send(result.response);
})
);
}

function runtimeContext(): RuntimeContext {
return { adapterId: "runtime" };
}
13 changes: 12 additions & 1 deletion App/backend/src/adapters/inbound/local-api/routes/channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
ChannelProviderSchema,
ConnectChannelInputSchema,
ConnectChannelResponseSchema,
OkResponseSchema
OkResponseSchema,
ReportIntegrationConnectionEventInputSchema
} from "@memmy/local-api-contracts";
import { z } from "zod";
import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
Expand Down Expand Up @@ -77,4 +78,14 @@ export function registerChannelRoutes(app: FastifyInstance, options: RegisterCha
return reply.send(response);
})
);

app.post(
"/api/v1/channels/connection-events",
{ preHandler: options.authenticateRuntimeToken },
withErrorEnvelope(async (request, reply) => {
const input = ReportIntegrationConnectionEventInputSchema.parse(request.body);
const response = OkResponseSchema.parse(await options.channels.reportConnectionEvent(input));
return reply.send(response);
})
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import {
AuthorizeIntegrationResponseSchema,
IntegrationCapabilitiesResponseSchema,
IntegrationConnectionsResponseSchema,
OkResponseSchema
OkResponseSchema,
ReportIntegrationConnectionEventInputSchema
} from "@memmy/local-api-contracts";
import { z } from "zod";
import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
Expand Down Expand Up @@ -54,6 +55,16 @@ export function registerIntegrationRoutes(app: FastifyInstance, options: Registe
})
);

app.post(
"/api/v1/integrations/connection-events",
{ preHandler: options.authenticateRuntimeToken },
withErrorEnvelope(async (request, reply) => {
const input = ReportIntegrationConnectionEventInputSchema.parse(request.body);
const response = OkResponseSchema.parse(await options.integrations.reportConnectionEvent(input));
return reply.send(response);
})
);

app.delete(
"/api/v1/integrations/connections/:id",
{ preHandler: options.authenticateRuntimeToken },
Expand Down
5 changes: 4 additions & 1 deletion App/backend/src/adapters/inbound/local-api/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@ const DEFAULT_HEARTBEAT_INTERVAL_MS = 15_000;
const LOCAL_API_SERVICE_NAME = "memmy-local-api";
const RUNTIME_TOKEN_HEADER = "x-memmy-local-token";
const CORS_ALLOWED_METHODS = "GET,POST,PUT,PATCH,DELETE,OPTIONS";
const CORS_ALLOWED_HEADERS = `content-type,${RUNTIME_TOKEN_HEADER}`;
const CORS_ALLOWED_HEADERS = `content-type,${RUNTIME_TOKEN_HEADER},x-memmy-time-zone`;
const DEFAULT_ALLOWED_LOCAL_HOSTS = new Set(["127.0.0.1", "localhost", "::1", "[::1]"]);
const OPAQUE_ORIGIN = "null";
const FILE_ORIGIN = "file://";

export interface CreateLocalApiServerOptions {
permissionManager: PermissionManager;
services: BackendServices;
/** Configured agent timezone. Renderer headers are used only when absent. */
timeZone?: string;
/**
* Local validation token for the Composio MCP bridge; the agent carries it in mcpServers.composio.headers to access /mcp/composio.
*/
Expand Down Expand Up @@ -133,6 +135,7 @@ export function createLocalApiServer(options: CreateLocalApiServerOptions): Fast
});
registerAgentRuntimeRoutes(app, {
services: options.services,
timeZone: options.timeZone,
authenticateRuntimeToken
});

Expand Down
Loading