@itz4blitz/agentful 1.0.0 → 1.0.2

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/bin/cli.js CHANGED
@@ -996,12 +996,300 @@ async function remote(args) {
996
996
  }
997
997
  }
998
998
 
999
+ /**
1000
+ * Get PID file path
1001
+ * @returns {string} Path to PID file
1002
+ */
1003
+ function getPidFilePath() {
1004
+ return path.join(process.cwd(), '.agentful', 'server.pid');
1005
+ }
1006
+
1007
+ /**
1008
+ * Start server in daemon mode
1009
+ * @param {string[]} args - Original args
1010
+ * @param {Object} config - Server configuration
1011
+ */
1012
+ async function startDaemon(args, config) {
1013
+ const { spawn } = await import('child_process');
1014
+
1015
+ // Check if daemon is already running
1016
+ const pidFile = getPidFilePath();
1017
+ if (fs.existsSync(pidFile)) {
1018
+ const pid = parseInt(fs.readFileSync(pidFile, 'utf-8').trim(), 10);
1019
+
1020
+ // Check if process is still running
1021
+ try {
1022
+ process.kill(pid, 0); // Signal 0 checks if process exists
1023
+ log(colors.yellow, 'Server is already running');
1024
+ log(colors.dim, `PID: ${pid}`);
1025
+ console.log('');
1026
+ log(colors.dim, 'To stop: agentful serve --stop');
1027
+ log(colors.dim, 'To check status: agentful serve --status');
1028
+ process.exit(1);
1029
+ } catch (error) {
1030
+ // Process doesn't exist, clean up stale PID file
1031
+ fs.unlinkSync(pidFile);
1032
+ }
1033
+ }
1034
+
1035
+ // Ensure .agentful directory exists
1036
+ const agentfulDir = path.join(process.cwd(), '.agentful');
1037
+ if (!fs.existsSync(agentfulDir)) {
1038
+ fs.mkdirSync(agentfulDir, { recursive: true });
1039
+ }
1040
+
1041
+ // Prepare args for child process (remove --daemon flag)
1042
+ const childArgs = args.filter(arg => !arg.startsWith('--daemon') && arg !== '-d');
1043
+
1044
+ // Create log files for daemon output
1045
+ const logFile = path.join(agentfulDir, 'server.log');
1046
+ const errLogFile = path.join(agentfulDir, 'server.err.log');
1047
+ const out = fs.openSync(logFile, 'a');
1048
+ const err = fs.openSync(errLogFile, 'a');
1049
+
1050
+ // Spawn detached child process
1051
+ const child = spawn(
1052
+ process.argv[0], // node executable
1053
+ [process.argv[1], 'serve', ...childArgs], // script path and args
1054
+ {
1055
+ detached: true,
1056
+ stdio: ['ignore', out, err],
1057
+ cwd: process.cwd(),
1058
+ env: {
1059
+ ...process.env,
1060
+ AGENTFUL_DAEMON: '1' // Flag to indicate we're running as daemon
1061
+ }
1062
+ }
1063
+ );
1064
+
1065
+ // Unref immediately to allow parent to exit independently
1066
+ child.unref();
1067
+
1068
+ // Wait for server to start (check health endpoint)
1069
+ const maxAttempts = 10;
1070
+ let started = false;
1071
+ for (let i = 0; i < maxAttempts; i++) {
1072
+ await new Promise(resolve => setTimeout(resolve, 500));
1073
+ try {
1074
+ const response = await fetch(`http://localhost:${config.port}/health`);
1075
+ if (response.ok) {
1076
+ started = true;
1077
+ break;
1078
+ }
1079
+ } catch {
1080
+ // Server not ready yet
1081
+ }
1082
+ }
1083
+
1084
+ if (!started) {
1085
+ log(colors.yellow, 'Warning: Server may not have started successfully');
1086
+ log(colors.dim, `Check logs: ${logFile}`);
1087
+ }
1088
+
1089
+ // Write PID file after confirming server started
1090
+ fs.writeFileSync(pidFile, child.pid.toString(), 'utf-8');
1091
+
1092
+ // Show success message
1093
+ log(colors.green, `Server started in background (PID: ${child.pid})`);
1094
+ console.log('');
1095
+ log(colors.dim, `PID file: ${pidFile}`);
1096
+ log(colors.dim, `Port: ${config.port}`);
1097
+ log(colors.dim, `Auth: ${config.auth}`);
1098
+ log(colors.dim, `Logs: ${logFile}`);
1099
+ console.log('');
1100
+ log(colors.dim, 'Commands:');
1101
+ log(colors.dim, ' agentful serve --stop Stop the daemon');
1102
+ log(colors.dim, ' agentful serve --status Check daemon status');
1103
+ console.log('');
1104
+ }
1105
+
1106
+ /**
1107
+ * Stop daemon server
1108
+ */
1109
+ async function stopDaemon() {
1110
+ const pidFile = getPidFilePath();
1111
+
1112
+ if (!fs.existsSync(pidFile)) {
1113
+ log(colors.yellow, 'No daemon server running');
1114
+ log(colors.dim, 'PID file not found');
1115
+ process.exit(1);
1116
+ }
1117
+
1118
+ const pid = parseInt(fs.readFileSync(pidFile, 'utf-8').trim(), 10);
1119
+
1120
+ // Try to kill the process
1121
+ try {
1122
+ process.kill(pid, 'SIGTERM');
1123
+
1124
+ // Wait a moment for graceful shutdown
1125
+ await new Promise(resolve => setTimeout(resolve, 1000));
1126
+
1127
+ // Check if process is still running
1128
+ try {
1129
+ process.kill(pid, 0);
1130
+ // Still running, force kill
1131
+ log(colors.yellow, 'Graceful shutdown failed, forcing...');
1132
+ process.kill(pid, 'SIGKILL');
1133
+ } catch {
1134
+ // Process stopped successfully
1135
+ }
1136
+
1137
+ // Remove PID file
1138
+ fs.unlinkSync(pidFile);
1139
+
1140
+ log(colors.green, `Server stopped (PID: ${pid})`);
1141
+ } catch (error) {
1142
+ if (error.code === 'ESRCH') {
1143
+ // Process doesn't exist
1144
+ log(colors.yellow, 'Server process not found (stale PID file)');
1145
+ fs.unlinkSync(pidFile);
1146
+ } else if (error.code === 'EPERM') {
1147
+ log(colors.red, `Permission denied to kill process ${pid}`);
1148
+ log(colors.dim, 'Try: sudo agentful serve --stop');
1149
+ process.exit(1);
1150
+ } else {
1151
+ log(colors.red, `Failed to stop server: ${error.message}`);
1152
+ process.exit(1);
1153
+ }
1154
+ }
1155
+ }
1156
+
1157
+ /**
1158
+ * Check daemon server status
1159
+ */
1160
+ async function checkDaemonStatus() {
1161
+ const pidFile = getPidFilePath();
1162
+
1163
+ if (!fs.existsSync(pidFile)) {
1164
+ log(colors.yellow, 'No daemon server running');
1165
+ log(colors.dim, 'PID file not found');
1166
+ console.log('');
1167
+ log(colors.dim, 'Start daemon: agentful serve --daemon');
1168
+ process.exit(1);
1169
+ }
1170
+
1171
+ const pid = parseInt(fs.readFileSync(pidFile, 'utf-8').trim(), 10);
1172
+
1173
+ // Check if process is running
1174
+ try {
1175
+ process.kill(pid, 0); // Signal 0 just checks if process exists
1176
+
1177
+ log(colors.green, 'Server is running');
1178
+ console.log('');
1179
+ log(colors.dim, `PID: ${pid}`);
1180
+ log(colors.dim, `PID file: ${pidFile}`);
1181
+
1182
+ // Try to get more info from /proc (Linux/macOS)
1183
+ try {
1184
+ const { execSync } = await import('child_process');
1185
+ const psOutput = execSync(`ps -p ${pid} -o comm,etime,rss`, { encoding: 'utf-8' });
1186
+ const lines = psOutput.trim().split('\n');
1187
+ if (lines.length > 1) {
1188
+ const [cmd, etime, rss] = lines[1].trim().split(/\s+/);
1189
+ console.log('');
1190
+ log(colors.dim, `Uptime: ${etime}`);
1191
+ log(colors.dim, `Memory: ${Math.round(parseInt(rss) / 1024)} MB`);
1192
+ }
1193
+ } catch {
1194
+ // ps command failed, skip detailed info
1195
+ }
1196
+
1197
+ console.log('');
1198
+ log(colors.dim, 'Commands:');
1199
+ log(colors.dim, ' agentful serve --stop Stop the daemon');
1200
+ } catch (error) {
1201
+ if (error.code === 'ESRCH') {
1202
+ log(colors.yellow, 'Server not running (stale PID file)');
1203
+ log(colors.dim, `PID file exists but process ${pid} not found`);
1204
+ console.log('');
1205
+ log(colors.dim, 'Clean up: rm .agentful/server.pid');
1206
+ process.exit(1);
1207
+ } else {
1208
+ log(colors.red, `Failed to check status: ${error.message}`);
1209
+ process.exit(1);
1210
+ }
1211
+ }
1212
+ }
1213
+
999
1214
  /**
1000
1215
  * Serve command - Start remote execution server
1001
1216
  */
1002
1217
  async function serve(args) {
1003
1218
  const flags = parseFlags(args);
1004
1219
 
1220
+ // Handle --stop subcommand
1221
+ if (flags.stop) {
1222
+ return await stopDaemon();
1223
+ }
1224
+
1225
+ // Handle --status subcommand
1226
+ if (flags.status) {
1227
+ return await checkDaemonStatus();
1228
+ }
1229
+
1230
+ // Handle --help flag first
1231
+ if (flags.help || flags.h) {
1232
+ showBanner();
1233
+ log(colors.bright, 'Agentful Remote Execution Server');
1234
+ console.log('');
1235
+ log(colors.dim, 'Start a secure HTTP server for remote agent execution.');
1236
+ console.log('');
1237
+ log(colors.bright, 'USAGE:');
1238
+ console.log(` ${colors.green}agentful serve${colors.reset} ${colors.dim}[options]${colors.reset}`);
1239
+ console.log('');
1240
+ log(colors.bright, 'AUTHENTICATION MODES:');
1241
+ console.log(` ${colors.cyan}--auth=tailscale${colors.reset} ${colors.dim}(default) Tailscale network only${colors.reset}`);
1242
+ console.log(` ${colors.cyan}--auth=hmac${colors.reset} ${colors.dim}HMAC signature authentication (requires --secret)${colors.reset}`);
1243
+ console.log(` ${colors.cyan}--auth=none${colors.reset} ${colors.dim}No authentication (binds to all interfaces, use with SSH tunnel)${colors.reset}`);
1244
+ console.log('');
1245
+ log(colors.bright, 'OPTIONS:');
1246
+ console.log(` ${colors.yellow}--port=<number>${colors.reset} ${colors.dim}Server port (default: 3000)${colors.reset}`);
1247
+ console.log(` ${colors.yellow}--secret=<key>${colors.reset} ${colors.dim}HMAC secret key (required for --auth=hmac)${colors.reset}`);
1248
+ console.log(` ${colors.yellow}--https${colors.reset} ${colors.dim}Enable HTTPS (requires --cert and --key)${colors.reset}`);
1249
+ console.log(` ${colors.yellow}--cert=<path>${colors.reset} ${colors.dim}SSL certificate file path${colors.reset}`);
1250
+ console.log(` ${colors.yellow}--key=<path>${colors.reset} ${colors.dim}SSL private key file path${colors.reset}`);
1251
+ console.log(` ${colors.yellow}--daemon, -d${colors.reset} ${colors.dim}Run server in background (daemon mode)${colors.reset}`);
1252
+ console.log(` ${colors.yellow}--stop${colors.reset} ${colors.dim}Stop background server${colors.reset}`);
1253
+ console.log(` ${colors.yellow}--status${colors.reset} ${colors.dim}Check background server status${colors.reset}`);
1254
+ console.log(` ${colors.yellow}--help, -h${colors.reset} ${colors.dim}Show this help message${colors.reset}`);
1255
+ console.log('');
1256
+ log(colors.bright, 'EXAMPLES:');
1257
+ console.log('');
1258
+ log(colors.dim, ' # Start server with Tailscale auth (default)');
1259
+ console.log(` ${colors.green}agentful serve${colors.reset}`);
1260
+ console.log('');
1261
+ log(colors.dim, ' # Start server with HMAC authentication');
1262
+ console.log(` ${colors.green}agentful serve --auth=hmac --secret=your-secret-key${colors.reset}`);
1263
+ console.log('');
1264
+ log(colors.dim, ' # Start HTTPS server with HMAC auth');
1265
+ console.log(` ${colors.green}agentful serve --auth=hmac --secret=key --https --cert=cert.pem --key=key.pem${colors.reset}`);
1266
+ console.log('');
1267
+ log(colors.dim, ' # Start server without auth (public access, use SSH tunnel)');
1268
+ console.log(` ${colors.green}agentful serve --auth=none --port=3737${colors.reset}`);
1269
+ console.log('');
1270
+ log(colors.dim, ' # Start server in background (daemon mode)');
1271
+ console.log(` ${colors.green}agentful serve --daemon${colors.reset}`);
1272
+ console.log('');
1273
+ log(colors.dim, ' # Check daemon status');
1274
+ console.log(` ${colors.green}agentful serve --status${colors.reset}`);
1275
+ console.log('');
1276
+ log(colors.dim, ' # Stop daemon');
1277
+ console.log(` ${colors.green}agentful serve --stop${colors.reset}`);
1278
+ console.log('');
1279
+ log(colors.dim, ' # Generate HMAC secret');
1280
+ console.log(` ${colors.green}openssl rand -hex 32${colors.reset}`);
1281
+ console.log('');
1282
+ log(colors.dim, ' # Generate self-signed certificate');
1283
+ console.log(` ${colors.green}openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes${colors.reset}`);
1284
+ console.log('');
1285
+ log(colors.bright, 'SECURITY NOTES:');
1286
+ console.log(` ${colors.yellow}Tailscale mode:${colors.reset} Binds to 0.0.0.0, relies on Tailscale network isolation`);
1287
+ console.log(` ${colors.yellow}HMAC mode:${colors.reset} Binds to 0.0.0.0, uses cryptographic signatures (recommended for public networks)`);
1288
+ console.log(` ${colors.yellow}None mode:${colors.reset} Binds to 0.0.0.0, no authentication (use SSH tunnel: ssh -L 3000:localhost:3000 user@host)`);
1289
+ console.log('');
1290
+ return;
1291
+ }
1292
+
1005
1293
  // Parse configuration
1006
1294
  const config = {
1007
1295
  auth: flags.auth || 'tailscale',
@@ -1013,6 +1301,9 @@ async function serve(args) {
1013
1301
  projectRoot: process.cwd(),
1014
1302
  };
1015
1303
 
1304
+ // Check if --daemon flag is set
1305
+ const isDaemon = flags.daemon || flags.d;
1306
+
1016
1307
  // Validate auth mode
1017
1308
  const validAuthModes = ['tailscale', 'hmac', 'none'];
1018
1309
  if (!validAuthModes.includes(config.auth)) {
@@ -1027,8 +1318,15 @@ async function serve(args) {
1027
1318
  process.exit(1);
1028
1319
  }
1029
1320
 
1030
- // Show configuration
1031
- showBanner();
1321
+ // If daemon mode, fork the process
1322
+ if (isDaemon) {
1323
+ return await startDaemon(args, config);
1324
+ }
1325
+
1326
+ // Show configuration (skip banner if running as daemon child)
1327
+ if (!process.env.AGENTFUL_DAEMON) {
1328
+ showBanner();
1329
+ }
1032
1330
  log(colors.bright, 'Starting Agentful Server');
1033
1331
  console.log('');
1034
1332
  log(colors.dim, `Authentication: ${config.auth}`);
@@ -1036,8 +1334,8 @@ async function serve(args) {
1036
1334
  log(colors.dim, `HTTPS: ${config.https ? 'enabled' : 'disabled'}`);
1037
1335
 
1038
1336
  if (config.auth === 'none') {
1039
- log(colors.yellow, 'Warning: Server will only accept localhost connections');
1040
- log(colors.dim, 'Use SSH tunnel for remote access: ssh -L 3000:localhost:3000 user@host');
1337
+ log(colors.yellow, 'Warning: Server running with no authentication (binds to all interfaces)');
1338
+ log(colors.dim, 'Recommended: Use SSH tunnel for remote access: ssh -L 3000:localhost:3000 user@host');
1041
1339
  }
1042
1340
 
1043
1341
  if (config.auth === 'hmac' && !config.secret) {
@@ -194,24 +194,8 @@ export function createAuthMiddleware(mode, config = {}) {
194
194
  };
195
195
 
196
196
  case 'none':
197
- // None mode: Only allow localhost connections
197
+ // None mode: Allow all connections (use with SSH tunnel for security)
198
198
  return (req, res, next) => {
199
- const clientIP = req.socket.remoteAddress;
200
- const isLocalhost =
201
- clientIP === '127.0.0.1' ||
202
- clientIP === '::1' ||
203
- clientIP === '::ffff:127.0.0.1';
204
-
205
- if (!isLocalhost) {
206
- res.writeHead(403, { 'Content-Type': 'application/json' });
207
- return res.end(
208
- JSON.stringify({
209
- error: 'Forbidden',
210
- message: 'Server is in localhost-only mode. Use SSH tunnel or switch to tailscale/hmac mode.',
211
- })
212
- );
213
- }
214
-
215
199
  next();
216
200
  };
217
201
 
@@ -133,13 +133,15 @@ ${agent.instructions}
133
133
  * @param {string} [options.projectRoot] - Project root directory
134
134
  * @param {number} [options.timeout] - Execution timeout in ms
135
135
  * @param {Object} [options.env] - Additional environment variables
136
- * @returns {Promise<Object>} Execution result
136
+ * @param {boolean} [options.async=false] - If true, return immediately with executionId
137
+ * @returns {Promise<Object>} Execution result (or just executionId if async=true)
137
138
  */
138
139
  export async function executeAgent(agentName, task, options = {}) {
139
140
  const {
140
141
  projectRoot = process.cwd(),
141
142
  timeout = 10 * 60 * 1000, // 10 minutes default
142
143
  env = {},
144
+ async = false, // New option for non-blocking execution
143
145
  } = options;
144
146
 
145
147
  // Validate agent name to prevent path traversal
@@ -176,6 +178,55 @@ export async function executeAgent(agentName, task, options = {}) {
176
178
 
177
179
  executions.set(executionId, execution);
178
180
 
181
+ // If async mode, start execution in background and return immediately
182
+ if (async) {
183
+ // Start execution in background (don't await)
184
+ runAgentExecution(executionId, agentName, task, {
185
+ projectRoot,
186
+ timeout,
187
+ filteredEnv,
188
+ }).catch((error) => {
189
+ // Update execution with error if background execution fails
190
+ const exec = executions.get(executionId);
191
+ if (exec) {
192
+ exec.state = ExecutionState.FAILED;
193
+ exec.endTime = Date.now();
194
+ exec.error = error.message;
195
+ exec.exitCode = -1;
196
+ }
197
+ });
198
+
199
+ return {
200
+ executionId,
201
+ state: ExecutionState.PENDING,
202
+ message: 'Execution started in background',
203
+ };
204
+ }
205
+
206
+ // Synchronous mode - wait for completion and return full result
207
+ return runAgentExecution(executionId, agentName, task, {
208
+ projectRoot,
209
+ timeout,
210
+ filteredEnv,
211
+ });
212
+ }
213
+
214
+ /**
215
+ * Internal function to run agent execution
216
+ * @param {string} executionId - Execution ID
217
+ * @param {string} agentName - Agent name
218
+ * @param {string} task - Task description
219
+ * @param {Object} options - Execution options
220
+ * @returns {Promise<Object>} Execution result
221
+ */
222
+ async function runAgentExecution(executionId, agentName, task, options) {
223
+ const { projectRoot, timeout, filteredEnv } = options;
224
+ const execution = executions.get(executionId);
225
+
226
+ if (!execution) {
227
+ throw new Error(`Execution ${executionId} not found`);
228
+ }
229
+
179
230
  try {
180
231
  // Load agent definition
181
232
  const agent = await loadAgentDefinition(agentName, projectRoot);
@@ -243,24 +243,28 @@ export function createServer(config = {}) {
243
243
  );
244
244
  }
245
245
 
246
- // Execute agent (non-blocking)
247
- const result = executeAgent(body.agent, body.task, {
246
+ // Log agent execution request
247
+ console.log(`[${new Date().toISOString()}] Executing agent: ${body.agent}`);
248
+ console.log(`[${new Date().toISOString()}] Task: ${body.task}`);
249
+
250
+ // Start agent execution in background (async mode)
251
+ const executionTimeout = body.timeout || 10 * 60 * 1000; // Default 10 min for execution
252
+
253
+ const result = await executeAgent(body.agent, body.task, {
248
254
  projectRoot,
249
- timeout: body.timeout,
255
+ timeout: executionTimeout,
250
256
  env: body.env,
257
+ async: true, // Return immediately with executionId
251
258
  });
252
259
 
253
- // Don't await - return immediately with execution ID
254
- result.then(() => {}).catch(() => {}); // Prevent unhandled rejection
255
-
256
- const executionId = (await result).executionId;
260
+ console.log(`[${new Date().toISOString()}] Execution started: ${result.executionId}`);
257
261
 
258
262
  res.writeHead(202, { 'Content-Type': 'application/json' });
259
263
  res.end(
260
264
  JSON.stringify({
261
- executionId,
265
+ executionId: result.executionId,
262
266
  message: 'Agent execution started',
263
- statusUrl: `/status/${executionId}`,
267
+ statusUrl: `/status/${result.executionId}`,
264
268
  })
265
269
  );
266
270
  } catch (error) {
@@ -315,6 +319,13 @@ export function createServer(config = {}) {
315
319
 
316
320
  // Request handler
317
321
  const requestHandler = (req, res) => {
322
+ const startTime = Date.now();
323
+ const clientIP = req.socket.remoteAddress;
324
+
325
+ // Log incoming request
326
+ const timestamp = new Date().toISOString();
327
+ console.log(`[${timestamp}] ${req.method} ${req.url} from ${clientIP}`);
328
+
318
329
  // Add CORS headers (restricted by default)
319
330
  if (corsOrigin) {
320
331
  res.setHeader('Access-Control-Allow-Origin', corsOrigin);
@@ -328,14 +339,27 @@ export function createServer(config = {}) {
328
339
  // Handle preflight
329
340
  if (req.method === 'OPTIONS') {
330
341
  res.writeHead(204);
342
+ const duration = Date.now() - startTime;
343
+ console.log(`[${new Date().toISOString()}] Response sent: 204 (${duration}ms)`);
331
344
  return res.end();
332
345
  }
333
346
 
334
347
  // Apply rate limiting
335
348
  if (!checkRateLimit(req, res)) {
349
+ const duration = Date.now() - startTime;
350
+ console.log(`[${new Date().toISOString()}] Response sent: 429 Rate Limited (${duration}ms)`);
336
351
  return; // Rate limit exceeded, response already sent
337
352
  }
338
353
 
354
+ // Intercept res.end to log responses
355
+ const originalEnd = res.end;
356
+ res.end = function(...args) {
357
+ const duration = Date.now() - startTime;
358
+ const statusCode = res.statusCode;
359
+ console.log(`[${new Date().toISOString()}] Response sent: ${statusCode} (${duration}ms)`);
360
+ originalEnd.apply(res, args);
361
+ };
362
+
339
363
  // Capture raw body (needed for HMAC verification)
340
364
  captureRawBody(req, res, () => {
341
365
  // Apply authentication (except for /health)
@@ -384,8 +408,9 @@ export function createServer(config = {}) {
384
408
  server = http.createServer(requestHandler);
385
409
  }
386
410
 
387
- // Determine bind address based on auth mode
388
- const host = auth === 'none' ? '127.0.0.1' : '0.0.0.0';
411
+ // Always bind to all interfaces (0.0.0.0)
412
+ // Security is enforced through authentication middleware, not binding address
413
+ const host = '0.0.0.0';
389
414
 
390
415
  return {
391
416
  start: () => {
@@ -400,7 +425,7 @@ export function createServer(config = {}) {
400
425
  console.log(`Authentication mode: ${auth}`);
401
426
 
402
427
  if (auth === 'none') {
403
- console.log('Server is bound to localhost only - use SSH tunnel for remote access');
428
+ console.log('Warning: No authentication enabled - use SSH tunnel for secure remote access');
404
429
  }
405
430
 
406
431
  // Start periodic cleanup
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itz4blitz/agentful",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Human-in-the-loop development kit for Claude Code with smart product analysis and natural conversation",
5
5
  "type": "module",
6
6
  "bin": {
package/version.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "0.5.1"
2
+ "version": "1.0.1"
3
3
  }