@toolplex/client 0.1.26 → 0.1.27

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.
@@ -20,6 +20,22 @@ const bundledDependencies = {
20
20
  uvx: process.env.TOOLPLEX_UVX_PATH,
21
21
  git: process.env.TOOLPLEX_GIT_PATH,
22
22
  };
23
+ // Parse session resume history for restored chat sessions
24
+ // This allows the enforcement layer to validate save_playbook and submit_feedback
25
+ // based on historical tool usage from the database
26
+ let sessionResumeHistory;
27
+ if (process.env.TOOLPLEX_SESSION_RESUME_HISTORY) {
28
+ try {
29
+ sessionResumeHistory = JSON.parse(process.env.TOOLPLEX_SESSION_RESUME_HISTORY);
30
+ FileLogger.info(`Parsed session resume history - ` +
31
+ `${sessionResumeHistory?.tool_calls.length || 0} tool calls, ` +
32
+ `${sessionResumeHistory?.installs.length || 0} installs, ` +
33
+ `${sessionResumeHistory?.uninstalls.length || 0} uninstalls`);
34
+ }
35
+ catch (error) {
36
+ FileLogger.warn(`Failed to parse session resume history: ${error}`);
37
+ }
38
+ }
23
39
  if (!apiKey) {
24
40
  process.exit(1);
25
41
  }
@@ -30,6 +46,7 @@ const config = {
30
46
  clientName,
31
47
  logLevel,
32
48
  bundledDependencies,
49
+ sessionResumeHistory,
33
50
  };
34
51
  serve(config).catch(() => {
35
52
  process.exit(1);
@@ -2,6 +2,10 @@ declare class CallToolObserver {
2
2
  private serverToolCalls;
3
3
  constructor();
4
4
  recordCall(serverId: string, toolName: string): void;
5
+ seedHistory(history: Array<{
6
+ server_id: string;
7
+ tool_name: string;
8
+ }>): void;
5
9
  wasServerCalled(serverId: string): boolean;
6
10
  wasToolCalled(serverId: string, toolName: string): boolean;
7
11
  clear(): void;
@@ -9,6 +9,12 @@ class CallToolObserver {
9
9
  }
10
10
  this.serverToolCalls.get(serverId).add(toolName);
11
11
  }
12
+ // Seed the observer with historical tool calls (for session resume)
13
+ seedHistory(history) {
14
+ history.forEach(({ server_id, tool_name }) => {
15
+ this.recordCall(server_id, tool_name);
16
+ });
17
+ }
12
18
  // Check if a server was called at all
13
19
  wasServerCalled(serverId) {
14
20
  return (this.serverToolCalls.has(serverId) &&
@@ -3,6 +3,11 @@ declare class InstallObserver {
3
3
  constructor();
4
4
  recordInstall(serverId: string): void;
5
5
  recordUninstall(serverId: string): void;
6
+ seedHistory(installs: Array<{
7
+ server_id: string;
8
+ }>, uninstalls: Array<{
9
+ server_id: string;
10
+ }>): void;
6
11
  wasServerInstalled(serverId: string): boolean;
7
12
  wasServerUninstalled(serverId: string): boolean;
8
13
  clear(): void;
@@ -10,6 +10,15 @@ class InstallObserver {
10
10
  recordUninstall(serverId) {
11
11
  this.recordAction(serverId, "uninstall");
12
12
  }
13
+ // Seed the observer with historical install/uninstall actions (for session resume)
14
+ seedHistory(installs, uninstalls) {
15
+ installs.forEach(({ server_id }) => {
16
+ this.recordInstall(server_id);
17
+ });
18
+ uninstalls.forEach(({ server_id }) => {
19
+ this.recordUninstall(server_id);
20
+ });
21
+ }
13
22
  // Check if a server has been installed
14
23
  wasServerInstalled(serverId) {
15
24
  return (this.serverInstallActions.has(serverId) &&
@@ -6,7 +6,7 @@ import { PromptsCache } from "./promptsCache.js";
6
6
  import { ToolDefinitionsCache } from "./toolDefinitionsCache.js";
7
7
  import { ServersCache } from "./serversCache.js";
8
8
  import { PolicyEnforcer } from "./policy/policyEnforcer.js";
9
- import { BundledDependencies } from "../shared/mcpServerTypes.js";
9
+ import { BundledDependencies, ToolplexServerConfig } from "../shared/mcpServerTypes.js";
10
10
  /**
11
11
  * In-memory global registry for the ToolPlex client.
12
12
  * Maintains singleton instances of core services and clients used throughout the application.
@@ -21,6 +21,7 @@ declare class Registry {
21
21
  private static _serversCache;
22
22
  private static _policyEnforcer;
23
23
  private static _bundledDependencies;
24
+ private static _serverConfig;
24
25
  static init(clientContext: ClientContext): Promise<void>;
25
26
  static getClientContext(): ClientContext;
26
27
  static getToolplexApiService(): ToolplexApiService;
@@ -46,6 +47,14 @@ declare class Registry {
46
47
  * Returns undefined if the dependency is not available.
47
48
  */
48
49
  static getBundledDependencyPath(depName: "node" | "python" | "git" | "uvx" | "npx"): string | undefined;
50
+ /**
51
+ * Set the server configuration (includes session resume history).
52
+ */
53
+ static setServerConfig(config: ToolplexServerConfig): void;
54
+ /**
55
+ * Get the server configuration.
56
+ */
57
+ static getServerConfig(): ToolplexServerConfig;
49
58
  static reset(): void;
50
59
  }
51
60
  export default Registry;
@@ -101,6 +101,21 @@ class Registry {
101
101
  static getBundledDependencyPath(depName) {
102
102
  return this._bundledDependencies[depName];
103
103
  }
104
+ /**
105
+ * Set the server configuration (includes session resume history).
106
+ */
107
+ static setServerConfig(config) {
108
+ this._serverConfig = config;
109
+ }
110
+ /**
111
+ * Get the server configuration.
112
+ */
113
+ static getServerConfig() {
114
+ if (!this._serverConfig) {
115
+ throw new Error("ServerConfig not set in Registry");
116
+ }
117
+ return this._serverConfig;
118
+ }
104
119
  static reset() {
105
120
  this._clientContext = null;
106
121
  this._toolplexApiService = null;
@@ -120,6 +135,7 @@ class Registry {
120
135
  }
121
136
  this._policyEnforcer = null;
122
137
  this._bundledDependencies = {};
138
+ this._serverConfig = null;
123
139
  }
124
140
  }
125
141
  Registry._clientContext = null;
@@ -131,4 +147,5 @@ Registry._toolDefinitionsCache = null;
131
147
  Registry._serversCache = null;
132
148
  Registry._policyEnforcer = null;
133
149
  Registry._bundledDependencies = {};
150
+ Registry._serverConfig = null;
134
151
  export default Registry;
@@ -100,6 +100,21 @@ export async function handleInitialize(params) {
100
100
  promptsCache.init(processedPrompts);
101
101
  // Init PolicyEnforce after setting permissions and flags
102
102
  policyEnforcer.init(clientContext);
103
+ // Seed enforcement history if provided (for restored sessions)
104
+ const serverConfig = Registry.getServerConfig();
105
+ if (serverConfig.sessionResumeHistory) {
106
+ const { tool_calls, installs, uninstalls } = serverConfig.sessionResumeHistory;
107
+ await logger.info(`Seeding enforcement history from restored session - ` +
108
+ `${tool_calls.length} tool calls, ${installs.length} installs, ${uninstalls.length} uninstalls`);
109
+ const callToolObserver = policyEnforcer.getCallToolObserver();
110
+ callToolObserver.seedHistory(tool_calls);
111
+ const installObserver = policyEnforcer.getInstallObserver();
112
+ installObserver.seedHistory(installs, uninstalls);
113
+ await logger.info("Enforcement history seeded successfully");
114
+ }
115
+ else {
116
+ await logger.debug("No session resume history provided (new session)");
117
+ }
103
118
  const allSucceeded = serverManagerInitResults.succeeded;
104
119
  const allFailures = serverManagerInitResults.failures;
105
120
  // Initialize the serversCache with the succeeded servers
@@ -39,6 +39,8 @@ export async function serve(config) {
39
39
  Registry.setBundledDependencies(config.bundledDependencies);
40
40
  await logger.debug(`Bundled dependencies registered: ${JSON.stringify(config.bundledDependencies)}`);
41
41
  }
42
+ // Store server config in Registry (includes session resume history)
43
+ Registry.setServerConfig(config);
42
44
  await logger.info(`Starting Toolplex server in ${config.dev ? "development" : "production"} mode`);
43
45
  const server = new Server({
44
46
  name: "toolplex-server",
@@ -21,6 +21,18 @@ export interface ToolplexServerConfig {
21
21
  clientName: string;
22
22
  logLevel: LogLevel;
23
23
  bundledDependencies?: BundledDependencies;
24
+ sessionResumeHistory?: {
25
+ tool_calls: Array<{
26
+ server_id: string;
27
+ tool_name: string;
28
+ }>;
29
+ installs: Array<{
30
+ server_id: string;
31
+ }>;
32
+ uninstalls: Array<{
33
+ server_id: string;
34
+ }>;
35
+ };
24
36
  }
25
37
  export declare const TransportTypeSchema: z.ZodEnum<["stdio", "sse"]>;
26
38
  export type TransportType = z.infer<typeof TransportTypeSchema>;
@@ -9,6 +9,12 @@ class CallToolObserver {
9
9
  }
10
10
  this.serverToolCalls.get(serverId).add(toolName);
11
11
  }
12
+ // Seed the observer with historical tool calls (for session resume)
13
+ seedHistory(history) {
14
+ history.forEach(({ server_id, tool_name }) => {
15
+ this.recordCall(server_id, tool_name);
16
+ });
17
+ }
12
18
  // Check if a server was called at all
13
19
  wasServerCalled(serverId) {
14
20
  return (this.serverToolCalls.has(serverId) &&
@@ -10,6 +10,15 @@ class InstallObserver {
10
10
  recordUninstall(serverId) {
11
11
  this.recordAction(serverId, "uninstall");
12
12
  }
13
+ // Seed the observer with historical install/uninstall actions (for session resume)
14
+ seedHistory(installs, uninstalls) {
15
+ installs.forEach(({ server_id }) => {
16
+ this.recordInstall(server_id);
17
+ });
18
+ uninstalls.forEach(({ server_id }) => {
19
+ this.recordUninstall(server_id);
20
+ });
21
+ }
13
22
  // Check if a server has been installed
14
23
  wasServerInstalled(serverId) {
15
24
  return (this.serverInstallActions.has(serverId) &&
@@ -101,6 +101,21 @@ class Registry {
101
101
  static getBundledDependencyPath(depName) {
102
102
  return this._bundledDependencies[depName];
103
103
  }
104
+ /**
105
+ * Set the server configuration (includes session resume history).
106
+ */
107
+ static setServerConfig(config) {
108
+ this._serverConfig = config;
109
+ }
110
+ /**
111
+ * Get the server configuration.
112
+ */
113
+ static getServerConfig() {
114
+ if (!this._serverConfig) {
115
+ throw new Error("ServerConfig not set in Registry");
116
+ }
117
+ return this._serverConfig;
118
+ }
104
119
  static reset() {
105
120
  this._clientContext = null;
106
121
  this._toolplexApiService = null;
@@ -120,6 +135,7 @@ class Registry {
120
135
  }
121
136
  this._policyEnforcer = null;
122
137
  this._bundledDependencies = {};
138
+ this._serverConfig = null;
123
139
  }
124
140
  }
125
141
  Registry._clientContext = null;
@@ -131,4 +147,5 @@ Registry._toolDefinitionsCache = null;
131
147
  Registry._serversCache = null;
132
148
  Registry._policyEnforcer = null;
133
149
  Registry._bundledDependencies = {};
150
+ Registry._serverConfig = null;
134
151
  export default Registry;
@@ -100,6 +100,21 @@ export async function handleInitialize(params) {
100
100
  promptsCache.init(processedPrompts);
101
101
  // Init PolicyEnforce after setting permissions and flags
102
102
  policyEnforcer.init(clientContext);
103
+ // Seed enforcement history if provided (for restored sessions)
104
+ const serverConfig = Registry.getServerConfig();
105
+ if (serverConfig.sessionResumeHistory) {
106
+ const { tool_calls, installs, uninstalls } = serverConfig.sessionResumeHistory;
107
+ await logger.info(`Seeding enforcement history from restored session - ` +
108
+ `${tool_calls.length} tool calls, ${installs.length} installs, ${uninstalls.length} uninstalls`);
109
+ const callToolObserver = policyEnforcer.getCallToolObserver();
110
+ callToolObserver.seedHistory(tool_calls);
111
+ const installObserver = policyEnforcer.getInstallObserver();
112
+ installObserver.seedHistory(installs, uninstalls);
113
+ await logger.info("Enforcement history seeded successfully");
114
+ }
115
+ else {
116
+ await logger.debug("No session resume history provided (new session)");
117
+ }
103
118
  const allSucceeded = serverManagerInitResults.succeeded;
104
119
  const allFailures = serverManagerInitResults.failures;
105
120
  // Initialize the serversCache with the succeeded servers
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "0.1.26";
1
+ export declare const version = "0.1.27";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '0.1.26';
1
+ export const version = '0.1.27';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toolplex/client",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
4
4
  "author": "ToolPlex LLC",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "description": "The official ToolPlex client for AI agent tool discovery and execution",