@aion0/forge 0.9.15 → 0.9.16
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/RELEASE_NOTES.md +8 -5
- package/install.sh +18 -4
- package/lib/craft-sdk/server.ts +2 -2
- package/lib/crafts/runtime.ts +1 -1
- package/lib/flows.ts +1 -1
- package/lib/issue-scanner-gitlab.ts +2 -2
- package/lib/issue-scanner.ts +2 -2
- package/lib/jobs/scheduler.ts +4 -4
- package/lib/jobs/store.ts +3 -3
- package/lib/notifications.ts +2 -2
- package/lib/notify.ts +1 -1
- package/lib/pipeline-scheduler.ts +2 -2
- package/lib/pipeline.ts +1 -1
- package/lib/prompts/store.ts +1 -1
- package/lib/schedules/action-runner.ts +4 -4
- package/lib/schedules/scheduler.ts +7 -7
- package/lib/schedules/store.ts +4 -4
- package/lib/session-manager.ts +5 -5
- package/lib/session-watcher.ts +1 -1
- package/lib/skills.ts +2 -2
- package/lib/task-manager.ts +3 -3
- package/lib/telegram-bot.ts +1 -1
- package/lib/usage-scanner.ts +2 -2
- package/package.json +1 -1
- package/src/config/index.ts +2 -2
- package/src/core/memory/strategy.ts +1 -1
- package/src/core/providers/chat.ts +2 -2
- package/src/core/providers/registry.ts +2 -2
- package/src/core/session/manager.ts +5 -5
package/RELEASE_NOTES.md
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
# Forge v0.9.
|
|
1
|
+
# Forge v0.9.16
|
|
2
2
|
|
|
3
|
-
Released: 2026-05-
|
|
3
|
+
Released: 2026-05-28
|
|
4
4
|
|
|
5
|
-
## Changes since v0.9.
|
|
5
|
+
## Changes since v0.9.15
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
- fix: convert all @/ aliases in lib/ and src/ to relative paths
|
|
6
9
|
|
|
7
10
|
### Other
|
|
8
|
-
- fix(
|
|
11
|
+
- fix(chat): replace @/src/* aliases with relative paths in lib/
|
|
9
12
|
|
|
10
13
|
|
|
11
|
-
**Full Changelog**: https://github.com/aiwatching/forge/compare/v0.9.
|
|
14
|
+
**Full Changelog**: https://github.com/aiwatching/forge/compare/v0.9.15...v0.9.16
|
package/install.sh
CHANGED
|
@@ -76,11 +76,25 @@ if [ ${#missing_opts[@]} -gt 0 ]; then
|
|
|
76
76
|
fi
|
|
77
77
|
|
|
78
78
|
if [ "$1" = "local" ] || [ "$1" = "--local" ]; then
|
|
79
|
-
|
|
80
|
-
npm
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
# Build a real npm tarball from the current working tree and install it
|
|
80
|
+
# globally exactly the way `npm install -g @aion0/forge` would after a
|
|
81
|
+
# publish. This runs the `prepack` hook (bundles cli/mw.mjs), respects
|
|
82
|
+
# .npmignore, and uses npm (not pnpm) for the global install — so the
|
|
83
|
+
# behaviour matches what a real user gets from `forge upgrade`.
|
|
84
|
+
echo "[forge] Building from local source (npm pack flow)..."
|
|
85
|
+
SRC_DIR="$(pwd)"
|
|
86
|
+
echo "[forge] Running pnpm build..."
|
|
83
87
|
pnpm build || echo "[forge] Build completed with warnings (non-critical)"
|
|
88
|
+
echo "[forge] Packing tarball..."
|
|
89
|
+
PACK_DIR="$(mktemp -d -t forge-pack-XXXXXX)"
|
|
90
|
+
TARBALL="$(cd "$PACK_DIR" && npm pack "$SRC_DIR" --silent)"
|
|
91
|
+
TARBALL_PATH="$PACK_DIR/$TARBALL"
|
|
92
|
+
echo "[forge] Built $TARBALL_PATH"
|
|
93
|
+
echo "[forge] Uninstalling previous global install..."
|
|
94
|
+
npm uninstall -g @aion0/forge 2>/dev/null || true
|
|
95
|
+
echo "[forge] Installing tarball globally..."
|
|
96
|
+
(cd /tmp && npm install -g "$TARBALL_PATH")
|
|
97
|
+
rm -rf "$PACK_DIR"
|
|
84
98
|
else
|
|
85
99
|
echo "[forge] Installing from npm..."
|
|
86
100
|
rm -rf "$(npm root -g)/@aion0/forge" 2>/dev/null || true
|
package/lib/craft-sdk/server.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Server-side SDK — used by craft authors in their `server.ts` file.
|
|
2
2
|
|
|
3
|
-
import type { CraftServerDef, CraftRouteHandler } from '
|
|
3
|
+
import type { CraftServerDef, CraftRouteHandler } from '../crafts/types';
|
|
4
4
|
|
|
5
5
|
export function defineCraftServer(def: CraftServerDef): CraftServerDef {
|
|
6
6
|
// Identity wrapper for type checking + future validation hooks.
|
|
@@ -11,4 +11,4 @@ export function defineCraftServer(def: CraftServerDef): CraftServerDef {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
// Re-export types so authors can `import type { ... } from '@forge/craft/server'`.
|
|
14
|
-
export type { CraftServerDef, CraftRouteHandler, ForgeServerApi, CraftRouteHandlerCtx } from '
|
|
14
|
+
export type { CraftServerDef, CraftRouteHandler, ForgeServerApi, CraftRouteHandlerCtx } from '../crafts/types';
|
package/lib/crafts/runtime.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { execSync } from 'node:child_process';
|
|
|
6
6
|
import { tmpdir } from 'node:os';
|
|
7
7
|
import * as esbuild from 'esbuild';
|
|
8
8
|
import { pathToFileURL } from 'node:url';
|
|
9
|
-
import { createTask } from '
|
|
9
|
+
import { createTask } from '../task-manager';
|
|
10
10
|
import type { CraftDescriptor, CraftServerDef, CraftRouteHandler, ForgeServerApi } from './types';
|
|
11
11
|
|
|
12
12
|
// Module cache: dir → { mtimeMs, mod }
|
package/lib/flows.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { join } from 'node:path';
|
|
|
9
9
|
import YAML from 'yaml';
|
|
10
10
|
import { createTask } from './task-manager';
|
|
11
11
|
import { getProjectInfo } from './projects';
|
|
12
|
-
import type { Task } from '
|
|
12
|
+
import type { Task } from '../src/types';
|
|
13
13
|
import { getDataDir } from './dirs';
|
|
14
14
|
|
|
15
15
|
const FLOWS_DIR = join(getDataDir(), 'flows');
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import { execSync } from 'node:child_process';
|
|
17
|
-
import { getDb } from '
|
|
18
|
-
import { getDbPath } from '
|
|
17
|
+
import { getDb } from '../src/core/db/database';
|
|
18
|
+
import { getDbPath } from '../src/config';
|
|
19
19
|
import { startPipeline } from './pipeline';
|
|
20
20
|
|
|
21
21
|
function db() { return getDb(getDbPath()); }
|
package/lib/issue-scanner.ts
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { execSync } from 'node:child_process';
|
|
13
|
-
import { getDb } from '
|
|
14
|
-
import { getDbPath } from '
|
|
13
|
+
import { getDb } from '../src/core/db/database';
|
|
14
|
+
import { getDbPath } from '../src/config';
|
|
15
15
|
import { startPipeline } from './pipeline';
|
|
16
16
|
import { loadSettings } from './settings';
|
|
17
17
|
import { homedir } from 'node:os';
|
package/lib/jobs/scheduler.ts
CHANGED
|
@@ -14,13 +14,13 @@ import {
|
|
|
14
14
|
import { CronExpressionParser } from 'cron-parser';
|
|
15
15
|
import { ensureInstalledInProject } from '../skills';
|
|
16
16
|
import type { Job, JobRunStatus, PipelineDispatchParams, ChatDispatchParams } from './types';
|
|
17
|
-
import { dispatchTool } from '
|
|
17
|
+
import { dispatchTool } from '../chat/tool-dispatcher';
|
|
18
18
|
import { dispatchToPipeline, dispatchToChat, dispatchToChatSummary } from './dispatcher';
|
|
19
|
-
import { getDb } from '
|
|
20
|
-
import { getDbPath } from '
|
|
19
|
+
import { getDb } from '../../src/core/db/database';
|
|
20
|
+
import { getDbPath } from '../../src/config';
|
|
21
21
|
import { existsSync, readFileSync } from 'node:fs';
|
|
22
22
|
import { join as joinPath } from 'node:path';
|
|
23
|
-
import { getDataDir } from '
|
|
23
|
+
import { getDataDir } from '../dirs';
|
|
24
24
|
|
|
25
25
|
/** Reconcile stale pipeline_runs rows against the canonical JSON
|
|
26
26
|
* state on disk. Called before any count, so counts return real
|
package/lib/jobs/store.ts
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* created on first use (mirrors lib/issue-scanner.ts style).
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { getDb } from '
|
|
7
|
-
import { getDbPath } from '
|
|
6
|
+
import { getDb } from '../../src/core/db/database';
|
|
7
|
+
import { getDbPath } from '../../src/config';
|
|
8
8
|
import { randomUUID } from 'node:crypto';
|
|
9
|
-
import { toIsoUTC } from '
|
|
9
|
+
import { toIsoUTC } from '../iso-time';
|
|
10
10
|
import { CronExpressionParser } from 'cron-parser';
|
|
11
11
|
import type {
|
|
12
12
|
Job, JobRun, JobDispatch, CreateJobInput,
|
package/lib/notifications.ts
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Stores notifications in SQLite, auto-cleans based on retention setting.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { getDb } from '
|
|
7
|
-
import { getDbPath } from '
|
|
6
|
+
import { getDb } from '../src/core/db/database';
|
|
7
|
+
import { getDbPath } from '../src/config';
|
|
8
8
|
import { loadSettings } from './settings';
|
|
9
9
|
|
|
10
10
|
export interface Notification {
|
package/lib/notify.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { loadSettings } from './settings';
|
|
6
6
|
import { addNotification } from './notifications';
|
|
7
|
-
import type { Task } from '
|
|
7
|
+
import type { Task } from '../src/types';
|
|
8
8
|
|
|
9
9
|
/** Look up the shared pipelineTaskIds Set via globalThis Symbol.
|
|
10
10
|
* pipeline.ts populates it on module init; using the Symbol avoids
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* - config.scanType: 'github-issues' enables automatic issue scanning + dedup
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import { getDb } from '
|
|
13
|
-
import { getDbPath } from '
|
|
12
|
+
import { getDb } from '../src/core/db/database';
|
|
13
|
+
import { getDbPath } from '../src/config';
|
|
14
14
|
import { startPipeline, getPipeline } from './pipeline';
|
|
15
15
|
import { randomUUID } from 'node:crypto';
|
|
16
16
|
import { execSync } from 'node:child_process';
|
package/lib/pipeline.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { createTask, getTask, onTaskEvent, taskModelOverrides, taskAppendSystemP
|
|
|
14
14
|
import { getProjectInfo } from './projects';
|
|
15
15
|
import { loadSettings } from './settings';
|
|
16
16
|
import { getAgent, listAgents } from './agents';
|
|
17
|
-
import type { Task } from '
|
|
17
|
+
import type { Task } from '../src/types';
|
|
18
18
|
import { getDataDir } from './dirs';
|
|
19
19
|
|
|
20
20
|
const PIPELINES_DIR = join(getDataDir(), 'pipelines');
|
package/lib/prompts/store.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { existsSync, readFileSync, readdirSync, writeFileSync, unlinkSync, mkdirSync } from 'node:fs';
|
|
9
9
|
import { join } from 'node:path';
|
|
10
10
|
import YAML from 'yaml';
|
|
11
|
-
import { getDataDir } from '
|
|
11
|
+
import { getDataDir } from '../dirs';
|
|
12
12
|
import type { Prompt, CreatePromptInput, UpdatePromptInput } from './types';
|
|
13
13
|
|
|
14
14
|
function dir(): string {
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
* null and set to 'done'/'failed'/'skipped' atomically).
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import { getDb } from '
|
|
19
|
-
import { getDbPath } from '
|
|
18
|
+
import { getDb } from '../../src/core/db/database';
|
|
19
|
+
import { getDbPath } from '../../src/config';
|
|
20
20
|
import { getScheduleRun, getSchedule, setScheduleRunAction } from './store';
|
|
21
|
-
import { appendMessage, getSession } from '
|
|
22
|
-
import { loadSettings } from '
|
|
21
|
+
import { appendMessage, getSession } from '../chat/session-store';
|
|
22
|
+
import { loadSettings } from '../settings';
|
|
23
23
|
import type { Schedule, ScheduleRun, ScheduleActionStatus } from './types';
|
|
24
24
|
|
|
25
25
|
function db() { return getDb(getDbPath()); }
|
|
@@ -13,18 +13,18 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { CronExpressionParser } from 'cron-parser';
|
|
16
|
-
import { startPipeline, getWorkflow } from '
|
|
16
|
+
import { startPipeline, getWorkflow } from '../pipeline';
|
|
17
17
|
import {
|
|
18
18
|
createTask,
|
|
19
19
|
getTask,
|
|
20
20
|
onTaskEvent,
|
|
21
21
|
taskAppendSystemPromptOverrides,
|
|
22
|
-
} from '
|
|
23
|
-
import { getProjectInfo, SCRATCH_PROJECT_NAME } from '
|
|
24
|
-
import { ensureInstalledInProject } from '
|
|
25
|
-
import { getPrompt } from '
|
|
26
|
-
import { getDb } from '
|
|
27
|
-
import { getDbPath } from '
|
|
22
|
+
} from '../task-manager';
|
|
23
|
+
import { getProjectInfo, SCRATCH_PROJECT_NAME } from '../projects';
|
|
24
|
+
import { ensureInstalledInProject } from '../skills';
|
|
25
|
+
import { getPrompt } from '../prompts/store';
|
|
26
|
+
import { getDb } from '../../src/core/db/database';
|
|
27
|
+
import { getDbPath } from '../../src/config';
|
|
28
28
|
import {
|
|
29
29
|
ensureSchema,
|
|
30
30
|
listDueSchedules,
|
package/lib/schedules/store.ts
CHANGED
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
import { existsSync, readFileSync } from 'node:fs';
|
|
17
17
|
import { join as joinPath } from 'node:path';
|
|
18
18
|
import { randomUUID } from 'node:crypto';
|
|
19
|
-
import { getDb } from '
|
|
20
|
-
import { getDbPath } from '
|
|
21
|
-
import { getDataDir } from '
|
|
22
|
-
import { toIsoUTC } from '
|
|
19
|
+
import { getDb } from '../../src/core/db/database';
|
|
20
|
+
import { getDbPath } from '../../src/config';
|
|
21
|
+
import { getDataDir } from '../dirs';
|
|
22
|
+
import { toIsoUTC } from '../iso-time';
|
|
23
23
|
import type {
|
|
24
24
|
Schedule,
|
|
25
25
|
ScheduleRun,
|
package/lib/session-manager.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { getDb } from '
|
|
3
|
-
import { getDbPath, loadTemplate } from '
|
|
4
|
-
import { chatStream, type ChatResult } from '
|
|
5
|
-
import { getMemoryMessages } from '
|
|
6
|
-
import type { Session, SessionStatus, Message, ProviderName, MemoryConfig } from '
|
|
2
|
+
import { getDb } from '../src/core/db/database';
|
|
3
|
+
import { getDbPath, loadTemplate } from '../src/config';
|
|
4
|
+
import { chatStream, type ChatResult } from '../src/core/providers/chat';
|
|
5
|
+
import { getMemoryMessages } from '../src/core/memory/strategy';
|
|
6
|
+
import type { Session, SessionStatus, Message, ProviderName, MemoryConfig } from '../src/types';
|
|
7
7
|
|
|
8
8
|
// Re-export the SessionManager but as a singleton for server-side use
|
|
9
9
|
class SessionManager {
|
package/lib/session-watcher.ts
CHANGED
package/lib/skills.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
import { existsSync, readdirSync, statSync, readFileSync, writeFileSync, mkdirSync, rmSync, cpSync } from 'node:fs';
|
|
6
6
|
import { join, dirname, basename, relative, sep } from 'node:path';
|
|
7
7
|
import { homedir } from 'node:os';
|
|
8
|
-
import { getDb } from '
|
|
9
|
-
import { getDbPath } from '
|
|
8
|
+
import { getDb } from '../src/core/db/database';
|
|
9
|
+
import { getDbPath } from '../src/config';
|
|
10
10
|
import { loadSettings } from './settings';
|
|
11
11
|
|
|
12
12
|
type ItemType = 'skill' | 'command';
|
package/lib/task-manager.ts
CHANGED
|
@@ -7,14 +7,14 @@ import { randomUUID } from 'node:crypto';
|
|
|
7
7
|
import { spawn, execSync } from 'node:child_process';
|
|
8
8
|
import { realpathSync } from 'node:fs';
|
|
9
9
|
import * as pty from 'node-pty';
|
|
10
|
-
import { getDb } from '
|
|
11
|
-
import { getDbPath } from '
|
|
10
|
+
import { getDb } from '../src/core/db/database';
|
|
11
|
+
import { getDbPath } from '../src/config';
|
|
12
12
|
import { loadSettings } from './settings';
|
|
13
13
|
import { notifyTaskComplete, notifyTaskFailed } from './notify';
|
|
14
14
|
import { getInstalledConnector } from './connectors/registry';
|
|
15
15
|
import { getAgent } from './agents';
|
|
16
16
|
import { recordUsage } from './usage-scanner';
|
|
17
|
-
import type { Task, TaskLogEntry, TaskStatus, TaskMode, WatchConfig } from '
|
|
17
|
+
import type { Task, TaskLogEntry, TaskStatus, TaskMode, WatchConfig } from '../src/types';
|
|
18
18
|
|
|
19
19
|
import { toIsoUTC } from './iso-time';
|
|
20
20
|
|
package/lib/telegram-bot.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { listClaudeSessions, getSessionFilePath, readSessionEntries } from './cl
|
|
|
14
14
|
import { listWatchers, createWatcher, deleteWatcher, toggleWatcher } from './session-watcher';
|
|
15
15
|
import { startTunnel, stopTunnel, getTunnelStatus } from './cloudflared';
|
|
16
16
|
// Password verification is done via require() in handler functions
|
|
17
|
-
import type { Task, TaskLogEntry } from '
|
|
17
|
+
import type { Task, TaskLogEntry } from '../src/types';
|
|
18
18
|
|
|
19
19
|
// Persist state across hot-reloads
|
|
20
20
|
const globalKey = Symbol.for('mw-telegram-state');
|
package/lib/usage-scanner.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
import { readdirSync, readFileSync, statSync } from 'node:fs';
|
|
7
7
|
import { join, basename } from 'node:path';
|
|
8
|
-
import { getDb } from '
|
|
9
|
-
import { getDbPath } from '
|
|
8
|
+
import { getDb } from '../src/core/db/database';
|
|
9
|
+
import { getDbPath } from '../src/config';
|
|
10
10
|
import { getClaudeDir } from './dirs';
|
|
11
11
|
|
|
12
12
|
function db() { return getDb(getDbPath()); }
|
package/package.json
CHANGED
package/src/config/index.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import YAML from 'yaml';
|
|
4
|
-
import type { AppConfig, ProviderName, SessionTemplate } from '
|
|
5
|
-
import { getConfigDir as _getConfigDir, getDataDir as _getDataDir } from '
|
|
4
|
+
import type { AppConfig, ProviderName, SessionTemplate } from '../types';
|
|
5
|
+
import { getConfigDir as _getConfigDir, getDataDir as _getDataDir } from '../../lib/dirs';
|
|
6
6
|
|
|
7
7
|
const CONFIG_DIR = _getConfigDir();
|
|
8
8
|
const CONFIG_FILE = join(CONFIG_DIR, 'config.yaml');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { streamText, generateText, type ModelMessage } from 'ai';
|
|
2
|
-
import { getModel } from '
|
|
3
|
-
import type { ProviderName } from '
|
|
2
|
+
import { getModel } from './registry';
|
|
3
|
+
import type { ProviderName } from '../../types';
|
|
4
4
|
|
|
5
5
|
export interface ChatOptions {
|
|
6
6
|
provider: ProviderName;
|
|
@@ -2,8 +2,8 @@ import { createAnthropic } from '@ai-sdk/anthropic';
|
|
|
2
2
|
import { createGoogleGenerativeAI } from '@ai-sdk/google';
|
|
3
3
|
import { createOpenAI } from '@ai-sdk/openai';
|
|
4
4
|
import type { LanguageModel } from 'ai';
|
|
5
|
-
import { loadConfig, getProviderApiKey } from '
|
|
6
|
-
import type { ProviderName } from '
|
|
5
|
+
import { loadConfig, getProviderApiKey } from '../../config';
|
|
6
|
+
import type { ProviderName } from '../../types';
|
|
7
7
|
|
|
8
8
|
const providerInstances = new Map<string, LanguageModel>();
|
|
9
9
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import type { ModelMessage } from 'ai';
|
|
3
|
-
import { getDb } from '
|
|
4
|
-
import { getDbPath, loadTemplate } from '
|
|
5
|
-
import { chatStream, type ChatResult } from '
|
|
6
|
-
import { getMemoryMessages } from '
|
|
7
|
-
import type { Session, SessionStatus, Message, ProviderName, MemoryConfig } from '
|
|
3
|
+
import { getDb } from '../db/database';
|
|
4
|
+
import { getDbPath, loadTemplate } from '../../config';
|
|
5
|
+
import { chatStream, type ChatResult } from '../providers/chat';
|
|
6
|
+
import { getMemoryMessages } from '../memory/strategy';
|
|
7
|
+
import type { Session, SessionStatus, Message, ProviderName, MemoryConfig } from '../../types';
|
|
8
8
|
|
|
9
9
|
export class SessionManager {
|
|
10
10
|
private db;
|