Skip to content

Commit

Permalink
Electron app working, adding binary and moving src folder
Browse files Browse the repository at this point in the history
  • Loading branch information
daffl committed Oct 3, 2015
1 parent 921b166 commit 9ce7b24
Show file tree
Hide file tree
Showing 19 changed files with 234 additions and 84 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -26,3 +26,4 @@ node_modules

.idea/
db-data/
lib/
3 changes: 3 additions & 0 deletions .npmignore
@@ -0,0 +1,3 @@
!lib/
src/
test/
27 changes: 27 additions & 0 deletions bin/mysam
@@ -0,0 +1,27 @@
#!/usr/bin/env node

var path = require('path');
var program = require('commander');
var root = path.join(__dirname, '..');
var pkg = require(path.join(root, 'package.json'));
var electron = require('electron-prebuilt');
var proc = require('child_process');

program.version(pkg.version)
.usage('[options]')
.description(pkg.description)
.option('-s, --server', 'Run server only')
.option('-d --develop', 'Run in development mode')
.parse(process.argv);

process.env.NODE_ENV = program.develop ? 'development' : 'production';

if(program.develop) {
process.env.DEBUG = process.env.DEBUG ? process.env.DEBUG + ',mysam:*' : 'mysam:*';
}

if(program.server) {
require('../lib/server');
} else {
proc.spawn(electron, [root], {stdio: 'inherit'});
}
4 changes: 4 additions & 0 deletions config.json
@@ -0,0 +1,4 @@
{
"port": 9090,
"frontend": "mysam-frontend"
}
17 changes: 0 additions & 17 deletions lib/app.js

This file was deleted.

2 changes: 0 additions & 2 deletions lib/index.js

This file was deleted.

50 changes: 0 additions & 50 deletions lib/plugins.js

This file was deleted.

23 changes: 17 additions & 6 deletions package.json
@@ -1,22 +1,32 @@
{
"name": "mysam",
"version": "0.0.1",
"description": "An open, web based \"intelligent\" agent that can listen to you and learn.",
"main": "lib/index",
"description": "An open, web based \"intelligent\" assistant that can listen to you and learn.",
"main": "lib/electron",
"bin": {
"testee": "./bin/testee"
},
"scripts": {
"start": "node lib/",
"start": "node lib/server",
"electron": "electron .",
"compile": "babel src --out-dir lib",
"compile:watch": "babel src --out-dir lib --watch",
"test": "npm run jshint && npm run mocha",
"watch": "DEBUG=mysam:* supervisor --ignore node_modules/ --no-restart-on error lib/",
"jshint": "jshint lib/. test/. --config",
"jshint": "jshint src/. test/. --config",
"mocha:watch": "mocha --compilers js:babel/register test/ --watch --recursive --growl --reporter Min",
"mocha": "mocha --compilers js:babel/register test/ --recursive"
},
"repository": {
"type": "git",
"url": "git@github.com:daffl/mysam.git"
},
"author": "David Luecke <daff@neyeon.com>",
"license": "MIT",
"dependencies": {
"babel": "^5.4.7",
"body-parser": "^1.13.0",
"commander": "^2.8.1",
"debug": "^2.2.0",
"electron-prebuilt": "^0.33.3",
"feathers": "^1.1.0-pre.0",
"feathers-hooks": "^0.5.0",
"feathers-memory": "^0.3.4",
Expand All @@ -28,6 +38,7 @@
"q": "^1.4.1"
},
"devDependencies": {
"babel": "^5.8.23",
"jshint": "^2.8.0",
"mocha": "^2.3.0",
"supervisor": "^0.6.0"
Expand Down
28 changes: 25 additions & 3 deletions readme.md
@@ -1,7 +1,29 @@
# Say hi to SAM
# Say hi SAM

[ ![Codeship Status for daffl/mysam](https://codeship.com/projects/b26a3f10-3c66-0133-d19d-1276d5d0a1e7/status?branch=master)](https://codeship.com/projects/102258)

An open source, web based "intelligent agent" that can listen to you and learn.
Sam is an open-source, web-based "intelligent" assistant. It can listen to you, learn new actions and easily be extended with JavaScript plugins. Sam runs as an [Electron](http://electron.atom.io/) desktop application or in a modern browser.

> I'm still very alpha...
# Installation

Install Sam globally via:

> npm install mysam -g
And then run either the desktop application with:

> mysam
Or the server (which is available at [localhost:9090](http://localhost:9090)) via:

> mysam --server
# Getting started

# Plugins

Plugins can be installed via [NPM](). To ask Sam about the weather run:

> npm install mysam-weather -g
Then restart the application.
28 changes: 28 additions & 0 deletions src/app.js
@@ -0,0 +1,28 @@
import bodyParser from 'body-parser';
import feathers from 'feathers';
import hooks from 'feathers-hooks';
import path from 'path';

import config from '../config.json';
import services from './services/index';
import loader from './loader';

const publicPath = path.join(__dirname, '..', 'node_modules', config.frontend);
const app = feathers()
.configure(feathers.rest())
.configure(feathers.socketio())
.configure(hooks())
.use(bodyParser.json())
.use(bodyParser.urlencoded({ extended: true }))
.use('/', function(req, res, next) {
if(req.url === '/' && process.env.NODE_ENV === 'production') {
return res.sendFile(path.join(publicPath, 'production.html'));
}

next();
})
.use('/', feathers.static(publicPath))
.configure(services)
.configure(loader);

export default app;
32 changes: 32 additions & 0 deletions src/electron.js
@@ -0,0 +1,32 @@
import app from 'app';
import BrowserWindow from 'browser-window';
import crashReporter from 'crash-reporter';

import server from './app';

const config = require('../config.json');

let mainWindow = null;

crashReporter.start();
server.listen(process.env.PORT || config.port);

app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});

app.on('ready', () => {
mainWindow = new BrowserWindow({
width: 800,
height: 600
});

mainWindow.loadUrl(`http://localhost:${config.port}`);
mainWindow.openDevTools();
mainWindow.on('closed', () => {
mainWindow = null;
});
});

File renamed without changes.
73 changes: 73 additions & 0 deletions src/loader.js
@@ -0,0 +1,73 @@
import Q from 'q';
import path from 'path';
import npm from 'npm';
import _ from 'lodash';
import debug from 'debug';
import feathers from 'feathers';

const log = debug('mysam:plugins');

export default function() {
const app = this;
const plugins = app.service('plugins');
const loadPlugin = moduleName => {
if(!moduleName){
return Q(null);
}

let pkgPath = require.resolve(path.join(moduleName, 'package.json'));
let pkg = require(pkgPath);
let config = pkg.mysam;

if(!config) {
return Q(null);
}

log(`Found plugin ${pkg.name}`);

let pluginLoader = require(moduleName);

if(typeof pluginLoader !== 'function') {
throw new Error(`Can not configure plugin ${pkg.name}`);
} else {
}
if(config.public) {
let dirname = path.dirname(pkgPath);
let staticPath = path.join(dirname, config.public);

log(`Setting up ${staticPath} at /${pkg.name}`);

app.use(`/${pkg.name}`, feathers.static(staticPath));
}

return Q.ninvoke(plugins, 'create', pkg)
.then(() => {
try {
let pluginLoader = require(moduleName);
app.configure(pluginLoader);
} catch(e) {
log(`No server configuration module for ${pkg.name}.`);
}
});
};

Q.ninvoke(npm, 'load', { loaded: false, global: true, depth: 0 })
.then(() => {
const dfd = Q.defer();

npm.commands.ls([], true, function (error, data) {
if(error) {
return dfd.reject(error);
}

let configurers = [];

_.each(data.dependencies, dependency =>
dependency && configurers.push(loadPlugin(dependency.path)));

dfd.resolve(Q.all(configurers));
});

return dfd.promise;
}).fail(error => console.error(error.stack));
}
5 changes: 5 additions & 0 deletions src/server.js
@@ -0,0 +1,5 @@
import app from './app';

const config = require('../config.json');

app.listen(process.env.PORT || config.port);
21 changes: 17 additions & 4 deletions lib/services/classify.js → src/services/classify.js
Expand Up @@ -3,6 +3,7 @@ import debug from 'debug';
import BrainJSClassifier from 'natural-brain';
import pos from 'pos';
import crypto from 'crypto';
import _ from 'lodash';

import Extractor from '../extractor';

Expand Down Expand Up @@ -34,7 +35,10 @@ export default {
create: [addPos, extract]
},
create(data, params, callback) {
log('Classifying', data);

if(this.retrain) {
log('Retraining Neural network');
this.classifier.retrain();
this.retrain = false;
}
Expand All @@ -46,7 +50,7 @@ export default {

Q.ninvoke(this.actions, 'get', action)
.then(action => {
return Object.assign(action, { id, input, classifications });
return _.extend(action, { id, input, classifications });
})
.then(result => {
log(result);
Expand All @@ -68,17 +72,26 @@ export default {
// We want to classify every word
BrainJSClassifier.disableStopWords();

this.classifier = new BrainJSClassifier();
this.app = app;
this.classifier = new BrainJSClassifier({
iterations: 2000
});

this.actions = app.service('actions');
this.actions.on('created', add);
//this.actions.on('removed', action => {
//
//});

Q.ninvoke(this.actions, 'find').then(list => {
list.forEach(add);
return list;
})
.then(list => list.length && this.classifier.train())
.then(list => {
if(list.length) {
this.classifier.train();
this.retrain = false;
}
})
.fail(error => log('ERROR: ', error.stack));
}
};
File renamed without changes.
File renamed without changes.

0 comments on commit 9ce7b24

Please sign in to comment.