Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
102 changes: 102 additions & 0 deletions .github/workflows/memory-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: Memory 2.1 Release

on:
workflow_dispatch:
inputs:
version:
description: Memory version (X.Y.Z)
required: true
default: 2.1.0
push:
tags:
- "memory-v*"

permissions:
contents: write

jobs:
verify:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run typecheck -w @memmy/memory
- run: npm test -w @memmy/memory
- run: npx vitest run App/shell/desktop/tests/packaged-runtime-boundary.test.ts App/shell/desktop/tests/runtime-services.test.ts

runtime:
needs: verify
strategy:
fail-fast: false
matrix:
include:
- target: darwin-arm64
os: macos-14
- target: darwin-x64
os: macos-15-intel
- target: linux-arm64
os: ubuntu-24.04-arm
- target: linux-x64
os: ubuntu-24.04
- target: windows-arm64
os: windows-11-arm
- target: windows-x64
os: windows-2025
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- name: Resolve version
id: version
shell: bash
run: |
version="${{ inputs.version }}"
if [[ -z "$version" ]]; then version="${GITHUB_REF_NAME#memory-v}"; fi
node -e 'if (!/^\d+\.\d+\.\d+$/.test(process.argv[1])) process.exit(1)' "$version"
echo "value=$version" >> "$GITHUB_OUTPUT"
- name: Build self-contained runtime
shell: bash
run: node Memory/src/cli/scripts/build-runtime.mjs --target "${{ matrix.target }}" --version "${{ steps.version.outputs.value }}" --output Memory/dist/release-part
- name: Build CLI launcher
shell: bash
env:
MEMMY_MEMORY_TARGET: ${{ matrix.target }}
MEMMY_MEMORY_VERSION: ${{ steps.version.outputs.value }}
run: bash Memory/src/cli/scripts/build-binary.sh
- uses: actions/upload-artifact@v4
with:
name: memory-${{ matrix.target }}
path: |
Memory/dist/release-part/*.tar.gz
Memory/src/cli/dist/binaries/*.tar.gz
if-no-files-found: error

publish:
needs: runtime
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
path: Memory/dist/release-input
- name: Resolve version
id: version
run: |
version="${{ inputs.version }}"
if [[ -z "$version" ]]; then version="${GITHUB_REF_NAME#memory-v}"; fi
echo "value=$version" >> "$GITHUB_OUTPUT"
- run: node Memory/src/cli/scripts/assemble-release.mjs Memory/dist/release-input Memory/dist/release "${{ steps.version.outputs.value }}"
- uses: softprops/action-gh-release@v2
with:
tag_name: memory-v${{ steps.version.outputs.value }}
name: Memmy Memory ${{ steps.version.outputs.value }}
generate_release_notes: true
files: Memory/dist/release/*
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ sessions/
.env.*
!.env.example
App/backend/src/adapters/outbound/skill-writer/workspace-bridge/memmy-workspace-bridge.mjs
Memory/src/agent-source/integration/workspace-bridge/memmy-workspace-bridge.mjs
30 changes: 27 additions & 3 deletions App/backend/local-api-contracts/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,15 @@ export const AppSettingsDtoSchema = z.object({
// Notification sound enabled.
notificationSoundEnabled: z.boolean().default(true),
// Menu bar icon enabled.
menuBarIconEnabled: z.boolean().default(true)
menuBarIconEnabled: z.boolean().default(true),
// Stop the standalone Memory daemon when Desktop exits.
stopMemoryServiceOnExit: z.boolean().default(false)
});
export type AppSettingsDto = z.infer<typeof AppSettingsDtoSchema>;

export const FirstEncounterReportStatusSchema = z.enum(["pending", "shown", "skipped"]);
export type FirstEncounterReportStatus = z.infer<typeof FirstEncounterReportStatusSchema>;

export const OnboardingStateDtoSchema = z.object({
// Completed.
completed: z.boolean(),
Expand All @@ -93,6 +98,8 @@ export const OnboardingStateDtoSchema = z.object({
acceptedTermsVersion: z.string().nullable(),
// Scan permission.
scanPermission: ScanPermissionSchema,
// Installation-local first encounter report state.
firstEncounterReportStatus: FirstEncounterReportStatusSchema.optional(),
// Improvement program.
improvementProgram: ImprovementProgramSchema,
// Completed at.
Expand Down Expand Up @@ -413,7 +420,12 @@ export type AgentSourceScanInput = z.infer<typeof AgentSourceScanInputSchema>;

export const OnboardingInsightReportInputSchema = z.object({
locale: z.enum(["zh-CN", "en-US"]).optional(),
stream: z.boolean().optional()
stream: z.boolean().optional(),
detectedAgents: z.array(z.object({
sourceId: z.string().min(1),
displayName: z.string().min(1),
recentSessionCount: z.number().int().nonnegative()
})).max(50).optional()
}).default({});
export type OnboardingInsightReportInput = z.infer<typeof OnboardingInsightReportInputSchema>;

Expand Down Expand Up @@ -598,7 +610,8 @@ export const PatchAppSettingsInputSchema = z
defaultLaunchMode: DefaultLaunchModeSchema,
taskDoneNotificationEnabled: z.boolean(),
notificationSoundEnabled: z.boolean(),
menuBarIconEnabled: z.boolean()
menuBarIconEnabled: z.boolean(),
stopMemoryServiceOnExit: z.boolean()
})
.partial();
export type PatchAppSettingsInput = z.infer<typeof PatchAppSettingsInputSchema>;
Expand Down Expand Up @@ -1022,11 +1035,22 @@ export const EffectiveModelCandidatesSchema = z.object({
});
export type EffectiveModelCandidates = z.infer<typeof EffectiveModelCandidatesSchema>;

/** Runtime ownership switches stored under ~/.memmy/config.yaml#memmyMemory. */
export const MemoryRuntimeModelSettingsSchema = z.object({
roleRouting: z.object({
summary: z.enum(["follow", "fixed"]),
evolution: z.enum(["follow", "fixed"])
}),
embeddingMode: z.enum(["cloud", "local", "custom"])
});
export type MemoryRuntimeModelSettings = z.infer<typeof MemoryRuntimeModelSettingsSchema>;

/** Schema for model config view. */
export const ModelConfigViewSchema = z.object({
configRevision: z.string().min(1),
providers: z.array(TextModelProviderViewSchema),
modelAssignments: ModelAssignmentsSchema,
memorySettings: MemoryRuntimeModelSettingsSchema.optional(),
effectiveCandidates: EffectiveModelCandidatesSchema,
configured: z.boolean(),
updatedAt: z.string().datetime()
Expand Down
10 changes: 8 additions & 2 deletions App/backend/local-api-contracts/src/memory-runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,10 @@ export type MemoryModelsStatus = z.infer<typeof MemoryModelsStatusSchema>;
/** Schema for memory health snapshot. */
export const MemoryHealthSnapshotSchema = z.object({
ok: z.boolean(),
serviceVersion: NonEmptyStringSchema.optional(),
protocolVersion: z.number().int().positive().optional(),
viewerVersion: NonEmptyStringSchema.optional(),
viewerUrl: z.url().optional(),
version: NonEmptyStringSchema,
uptimeMs: z.number().nonnegative(),
mode: z.enum(["local", "cloud", "dev"]),
Expand All @@ -314,7 +318,8 @@ export const MemoryHealthSnapshotSchema = z.object({
routes: z.array(z.string()),
tools: z.array(z.string()),
memoryLayers: z.array(MemoryLayerSchema),
supportsCli: z.boolean()
supportsCli: z.boolean(),
service: z.array(z.string()).optional()
}),
features: L3WorldModelFeaturesSchema.optional(),
models: MemoryModelsStatusSchema,
Expand Down Expand Up @@ -524,7 +529,8 @@ export const AddMemoryOutputSchema = z.object({
summary: z.string(),
tags: z.array(z.string()),
createdAt: IsoTimeSchema,
serverTime: IsoTimeSchema
serverTime: IsoTimeSchema,
duplicate: z.boolean().optional()
});
export type AddMemoryOutput = z.infer<typeof AddMemoryOutputSchema>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ export function registerAppConfigRoutes(app: FastifyInstance, options: RegisterA
})
);

app.get(
"/api/app/scan-preferences",
{ preHandler: options.authenticateRuntimeToken },
withErrorEnvelope(async (_request, reply) => {
const response = ScanPreferencesSchema.parse(await options.appConfig.getScanPreferences());
return reply.send(response);
})
);

app.patch(
"/api/app/onboarding",
{ preHandler: options.authenticateRuntimeToken },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
RetryMemoryProcessingOutputSchema,
WorkerRunOutputSchema
} from "@memmy/local-api-contracts";
import type { ZodType } from "zod";
import { z, type ZodType } from "zod";
import { MemoryLayerError, MemoryLayerNetworkError } from "./errors.js";
import { buildMemoryLayerUrl, MEMORY_LAYER_PATHS } from "./memory-layer-endpoints.js";
import { retryWithBackoff } from "./retry.js";
Expand Down Expand Up @@ -128,6 +128,18 @@ export function createHttpMemoryClient(
return request("POST", "reloadConfig", MemoryReloadConfigOutputSchema, { body: input });
},

async exportBundle() {
return request("GET", "exportBundle", z.record(z.string(), z.unknown()));
},

async clearAllData() {
return request("DELETE", "clearAllData", z.object({
ok: z.literal(true),
clearedAt: z.string(),
cleared: z.record(z.string(), z.number())
}), { body: {} });
},

async openSession(input, context) {
return request("POST", "openSession", OpenSessionOutputSchema, { body: input, context });
},
Expand Down
6 changes: 0 additions & 6 deletions App/backend/src/adapters/outbound/memory-client/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
export { createHttpMemoryClient, type CreateHttpMemoryClientOptions, type MemoryLayerConfig } from "./http-memory-client.js";
export { buildMemoryLayerUrl, MEMORY_LAYER_PATHS } from "./memory-layer-endpoints.js";
export {
createMemosSqliteMemoryClient,
discoverMemosSqliteSources,
type CreateMemosSqliteMemoryClientOptions,
type MemosSqliteSource
} from "./memos-sqlite-memory-client.js";
export { MemoryLayerError, MemoryLayerNetworkError } from "./errors.js";
export type { MemoryClient } from "./types.js";
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
export const MEMORY_LAYER_PATHS = Object.freeze({
health: "/api/v1/health",
reloadConfig: "/api/v1/admin/reload-config",
exportBundle: "/api/v1/admin/export",
clearAllData: "/api/v1/admin/data",
openSession: "/api/v1/sessions/open",
closeSession: "/api/v1/sessions/:sessionId/close",
startTurn: "/api/v1/turns/start",
Expand Down
Loading
Loading