1- Index: third-party -src/extensions/sagemaker-idle-extension/README.md
1+ Index: code-editor -src/extensions/sagemaker-idle-extension/README.md
22===================================================================
33--- /dev/null
4- +++ third-party -src/extensions/sagemaker-idle-extension/README.md
4+ +++ code-editor -src/extensions/sagemaker-idle-extension/README.md
55@@ -0,0 +1,3 @@
66+ # Code Editor Idle Extension
77+
88+ The Code Editor Idle Extension tracks user activity and logs the last active timestamp (in UTC) to a local file. User activities monitored include file changes, text editor selection changes, and terminal interactions. Additionally, it provides an API endpoint `/api/idle` that returns the lastActiveTimestamp.
99\ No newline at end of file
10- Index: third-party -src/extensions/sagemaker-idle-extension/extension-browser.webpack.config.js
10+ Index: code-editor -src/extensions/sagemaker-idle-extension/extension-browser.webpack.config.js
1111===================================================================
1212--- /dev/null
13- +++ third-party -src/extensions/sagemaker-idle-extension/extension-browser.webpack.config.js
13+ +++ code-editor -src/extensions/sagemaker-idle-extension/extension-browser.webpack.config.js
1414@@ -0,0 +1,17 @@
1515+ /*---------------------------------------------------------------------------------------------
1616+ * Copyright Amazon.com Inc. or its affiliates. All rights reserved.
@@ -29,10 +29,10 @@ Index: third-party-src/extensions/sagemaker-idle-extension/extension-browser.web
2929+ extension: './src/extension.ts'
3030+ },
3131+ });
32- Index: third-party -src/extensions/sagemaker-idle-extension/extension.webpack.config.js
32+ Index: code-editor -src/extensions/sagemaker-idle-extension/extension.webpack.config.js
3333===================================================================
3434--- /dev/null
35- +++ third-party -src/extensions/sagemaker-idle-extension/extension.webpack.config.js
35+ +++ code-editor -src/extensions/sagemaker-idle-extension/extension.webpack.config.js
3636@@ -0,0 +1,20 @@
3737+ /*---------------------------------------------------------------------------------------------
3838+ * Copyright Amazon.com Inc. or its affiliates. All rights reserved.
@@ -54,10 +54,10 @@ Index: third-party-src/extensions/sagemaker-idle-extension/extension.webpack.con
5454+ extension: './src/extension.ts',
5555+ }
5656+ });
57- Index: third-party -src/extensions/sagemaker-idle-extension/package.json
57+ Index: code-editor -src/extensions/sagemaker-idle-extension/package.json
5858===================================================================
5959--- /dev/null
60- +++ third-party -src/extensions/sagemaker-idle-extension/package.json
60+ +++ code-editor -src/extensions/sagemaker-idle-extension/package.json
6161@@ -0,0 +1,43 @@
6262+ {
6363+ "name": "sagemaker-idle-extension",
@@ -102,10 +102,10 @@ Index: third-party-src/extensions/sagemaker-idle-extension/package.json
102102+ "dependencies": {},
103103+ "repository": {}
104104+ }
105- Index: third-party -src/extensions/sagemaker-idle-extension/tsconfig.json
105+ Index: code-editor -src/extensions/sagemaker-idle-extension/tsconfig.json
106106===================================================================
107107--- /dev/null
108- +++ third-party -src/extensions/sagemaker-idle-extension/tsconfig.json
108+ +++ code-editor -src/extensions/sagemaker-idle-extension/tsconfig.json
109109@@ -0,0 +1,10 @@
110110+ {
111111+ "extends": "../tsconfig.base.json",
@@ -117,10 +117,10 @@ Index: third-party-src/extensions/sagemaker-idle-extension/tsconfig.json
117117+ "../../src/vscode-dts/vscode.d.ts"
118118+ ]
119119+ }
120- Index: third-party -src/extensions/sagemaker-idle-extension/.vscodeignore
120+ Index: code-editor -src/extensions/sagemaker-idle-extension/.vscodeignore
121121===================================================================
122122--- /dev/null
123- +++ third-party -src/extensions/sagemaker-idle-extension/.vscodeignore
123+ +++ code-editor -src/extensions/sagemaker-idle-extension/.vscodeignore
124124@@ -0,0 +1,11 @@
125125+ .vscode/**
126126+ .vscode-test/**
@@ -133,42 +133,35 @@ Index: third-party-src/extensions/sagemaker-idle-extension/.vscodeignore
133133+ out/**
134134+ cgmanifest.json
135135+ preview-src/**
136- Index: third-party -src/extensions/sagemaker-idle-extension/src/extension.ts
136+ Index: code-editor -src/extensions/sagemaker-idle-extension/src/extension.ts
137137===================================================================
138138--- /dev/null
139- +++ third-party -src/extensions/sagemaker-idle-extension/src/extension.ts
140- @@ -0,0 +1,112 @@
139+ +++ code-editor -src/extensions/sagemaker-idle-extension/src/extension.ts
140+ @@ -0,0 +1,59 @@
141141+ import * as vscode from "vscode";
142142+ import * as fs from "fs";
143143+ import * as path from "path";
144144+
145- + let idleFilePath: string
146- + let terminalActivityInterval: NodeJS.Timeout | undefined
147- + const LOG_PREFIX = "[sagemaker-idle-extension]"
148- + const CHECK_INTERVAL = 60000; // 60 seconds interval
145+ + let idleFilePath: string;
149146+
150147+ export function activate(context: vscode.ExtensionContext) {
151148+ initializeIdleFilePath();
152149+ registerEventListeners(context);
153150+ startMonitoringTerminalActivity();
154151+ }
155152+
156- + export function deactivate() {
157- + if(terminalActivityInterval) {
158- + clearInterval(terminalActivityInterval)
159- + }
160- + }
153+ + export function deactivate() {}
161154+
162155+ /**
163156+ * Initializes the file path where the idle timestamp will be stored.
164157+ * It sets the path to a hidden file in the /tmp/ directory.
165158+ */
166159+ function initializeIdleFilePath() {
167- + const tmpDirectory = "/tmp/";
160+ + const tmpDirectory = "/tmp/";
168161+ idleFilePath = path.join(tmpDirectory, ".sagemaker-last-active-timestamp");
169162+
170163+ // Set initial lastActivetimestamp
171- + updateLastActivityTimestamp()
164+ + updateLastActivityTimestamp();
172165+ }
173166+
174167+ /**
@@ -197,52 +190,6 @@ Index: third-party-src/extensions/sagemaker-idle-extension/src/extension.ts
197190+ }
198191+
199192+ /**
200- + * Starts monitoring terminal activity by setting an interval to check for activity in the /dev/pts directory.
201- + */
202- + const startMonitoringTerminalActivity = () => {
203- + terminalActivityInterval = setInterval(checkTerminalActivity, CHECK_INTERVAL);
204- + };
205- +
206- +
207- + /**
208- + * Checks for terminal activity by reading the /dev/pts directory and comparing modification times of the files.
209- + *
210- + * The /dev/pts directory is used in Unix-like operating systems to represent pseudo-terminal (PTY) devices.
211- + * Each active terminal session is assigned a PTY device. These devices are represented as files within the /dev/pts directory.
212- + * When a terminal session has activity, such as when a user inputs commands or output is written to the terminal,
213- + * the modification time (mtime) of the corresponding PTY device file is updated. By monitoring the modification
214- + * times of the files in the /dev/pts directory, we can detect terminal activity.
215- + *
216- + * If activity is detected (i.e., if any PTY device file was modified within the CHECK_INTERVAL), this function
217- + * updates the last activity timestamp.
218- + */
219- + const checkTerminalActivity = () => {
220- + fs.readdir("/dev/pts", (err, files) => {
221- + if (err) {
222- + console.error(`${LOG_PREFIX} Error reading /dev/pts directory:`, err);
223- + return;
224- + }
225- +
226- + const now = Date.now();
227- + const activityDetected = files.some((file) => {
228- + const filePath = path.join("/dev/pts", file);
229- + try {
230- + const stats = fs.statSync(filePath);
231- + const mtime = new Date(stats.mtime).getTime();
232- + return now - mtime < CHECK_INTERVAL;
233- + } catch (error) {
234- + console.error(`${LOG_PREFIX} Error reading file stats:`, error);
235- + return false;
236- + }
237- + });
238- +
239- + if (activityDetected) {
240- + updateLastActivityTimestamp();
241- + }
242- + });
243- + };
244- +
245- + /**
246193+ * Updates the last activity timestamp by recording the current timestamp in the idle file and
247194+ * refreshing the status bar. The timestamp should be in ISO 8601 format and set to the UTC timezone.
248195+ */
@@ -251,10 +198,10 @@ Index: third-party-src/extensions/sagemaker-idle-extension/src/extension.ts
251198+ fs.writeFileSync(idleFilePath, timestamp);
252199+ }
253200\ No newline at end of file
254- Index: third-party -src/build/gulpfile.extensions.js
201+ Index: code-editor -src/build/gulpfile.extensions.js
255202===================================================================
256- --- third-party -src.orig/build/gulpfile.extensions.js
257- +++ third-party -src/build/gulpfile.extensions.js
203+ --- code-editor -src.orig/build/gulpfile.extensions.js
204+ +++ code-editor -src/build/gulpfile.extensions.js
258205@@ -61,6 +61,7 @@ const compilations = [
259206 'extensions/search-result/tsconfig.json',
260207 'extensions/simple-browser/tsconfig.json',
@@ -263,10 +210,10 @@ Index: third-party-src/build/gulpfile.extensions.js
263210 'extensions/tunnel-forwarding/tsconfig.json',
264211 'extensions/typescript-language-features/test-workspace/tsconfig.json',
265212 'extensions/typescript-language-features/web/tsconfig.json',
266- Index: third-party -src/build/npm/dirs.js
213+ Index: code-editor -src/build/npm/dirs.js
267214===================================================================
268- --- third-party -src.orig/build/npm/dirs.js
269- +++ third-party -src/build/npm/dirs.js
215+ --- code-editor -src.orig/build/npm/dirs.js
216+ +++ code-editor -src/build/npm/dirs.js
270217@@ -39,6 +39,7 @@ const dirs = [
271218 'extensions/php-language-features',
272219 'extensions/references-view',
@@ -275,28 +222,68 @@ Index: third-party-src/build/npm/dirs.js
275222 'extensions/search-result',
276223 'extensions/simple-browser',
277224 'extensions/tunnel-forwarding',
278- Index: third-party -src/src/vs/server/node/webClientServer.ts
225+ Index: code-editor -src/src/vs/server/node/webClientServer.ts
279226===================================================================
280- --- third-party -src.orig/src/vs/server/node/webClientServer.ts
281- +++ third-party -src/src/vs/server/node/webClientServer.ts
282- @@ -3,7 +3,7 @@
227+ --- code-editor -src.orig/src/vs/server/node/webClientServer.ts
228+ +++ code-editor -src/src/vs/server/node/webClientServer.ts
229+ @@ -3,8 +3,9 @@
283230 * Licensed under the MIT License. See License.txt in the project root for license information.
284231 *--------------------------------------------------------------------------------------------*/
285232
286233- import { createReadStream, promises } from 'fs';
287- + import { createReadStream, promises, existsSync, writeFileSync } from 'fs';
234+ + import { createReadStream, promises, existsSync, readdirSync, statSync, writeFileSync } from 'fs';
288235 import * as http from 'http';
236+ + import * as path from 'path';
289237 import * as url from 'url';
290238 import * as cookie from 'cookie';
291- @@ -96,6 +96,7 @@ const APP_ROOT = dirname(FileAccess.asFi
239+ import * as crypto from 'crypto';
240+ @@ -91,11 +92,45 @@ export async function serveFile(filePath
241+ }
242+ }
243+
244+ + const CHECK_INTERVAL = 60000; // 60 seconds interval
245+ const APP_ROOT = dirname(FileAccess.asFileUri('').fsPath);
246+
292247 const STATIC_PATH = `/static`;
293248 const CALLBACK_PATH = `/callback`;
294249 const WEB_EXTENSION_PATH = `/web-extension-resource`;
295250+ const IDLE_EXTENSION_PATH = `/api/idle`;
251+ +
252+ + /**
253+ + * Checks for terminal activity by reading the /dev/pts directory and comparing modification times of the files.
254+ + *
255+ + * The /dev/pts directory is used in Unix-like operating systems to represent pseudo-terminal (PTY) devices.
256+ + * Each active terminal session is assigned a PTY device. These devices are represented as files within the /dev/pts directory.
257+ + * When a terminal session has activity, such as when a user inputs commands or output is written to the terminal,
258+ + * the modification time (mtime) of the corresponding PTY device file is updated. By monitoring the modification
259+ + * times of the files in the /dev/pts directory, we can detect terminal activity.
260+ + *
261+ + * If activity is detected (i.e., if any PTY device file was modified within the CHECK_INTERVAL), this function
262+ + * updates the last activity timestamp.
263+ + */
264+ + function checkTerminalActivity(idleFilePath: string) {
265+ + try {
266+ + const files: string[] = readdirSync('/dev/pts');
267+ + const now = new Date();
268+ +
269+ + const activityDetected = files.some((file: string) => {
270+ + const filePath = path.join('/dev/pts', file);
271+ + const stats = statSync(filePath);
272+ + const mtime = new Date(stats.mtime).getTime();
273+ + return now.getTime() - mtime < CHECK_INTERVAL;
274+ + });
275+ +
276+ + if (activityDetected) {
277+ + writeFileSync(idleFilePath, now.toISOString());
278+ + }
279+ + } catch (err) {
280+ + console.error('Error checking terminal activity:', err);
281+ + }
282+ + }
296283
297284 export class WebClientServer {
298285
299- @@ -133,6 +134 ,9 @@ export class WebClientServer {
286+ @@ -133,6 +168 ,9 @@ export class WebClientServer {
300287 // callback support
301288 return this._handleCallback(res);
302289 }
@@ -306,7 +293,7 @@ Index: third-party-src/src/vs/server/node/webClientServer.ts
306293 if (pathname.startsWith(WEB_EXTENSION_PATH) && pathname.charCodeAt(WEB_EXTENSION_PATH.length) === CharCode.Slash) {
307294 // extension resource support
308295 return this._handleWebExtensionResource(req, res, pathname.substring(WEB_EXTENSION_PATH.length));
309- @@ -505,6 +509,31 @@ export class WebClientServer {
296+ @@ -505,6 +543,33 @@ export class WebClientServer {
310297 });
311298 return void res.end(data);
312299 }
@@ -318,16 +305,18 @@ Index: third-party-src/src/vs/server/node/webClientServer.ts
318305+ try {
319306+ const tmpDirectory = '/tmp/'
320307+ const idleFilePath = join(tmpDirectory, '.sagemaker-last-active-timestamp');
321- +
308+ +
322309+ // If idle shutdown file does not exist, this indicates the app UI may never been opened
323310+ // Create the initial metadata file
324311+ if (!existsSync(idleFilePath)) {
325312+ const timestamp = new Date().toISOString();
326313+ writeFileSync(idleFilePath, timestamp);
327314+ }
328- +
315+ +
316+ + checkTerminalActivity(idleFilePath);
317+ +
329318+ const data = await promises.readFile(idleFilePath, 'utf8');
330- +
319+ +
331320+ res.statusCode = 200;
332321+ res.setHeader('Content-Type', 'application/json');
333322+ res.end(JSON.stringify({ lastActiveTimestamp: data }));
@@ -336,3 +325,5 @@ Index: third-party-src/src/vs/server/node/webClientServer.ts
336325+ }
337326+ }
338327 }
328+
329+
0 commit comments