@agi-cli/sdk 0.1.93 → 0.1.94

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agi-cli/sdk",
3
- "version": "0.1.93",
3
+ "version": "0.1.94",
4
4
  "description": "AI agent SDK for building intelligent assistants - tree-shakable and comprehensive",
5
5
  "author": "ntishxyz",
6
6
  "license": "MIT",
@@ -100,3 +100,9 @@ export {
100
100
  NotFoundError,
101
101
  ServiceError,
102
102
  } from './errors';
103
+
104
+ // =======================
105
+ // Logging & Debug
106
+ // =======================
107
+ export { logger, debug, info, warn, error, time } from './utils/logger.ts';
108
+ export { isDebugEnabled, isTraceEnabled } from './utils/debug.ts';
@@ -1,7 +1,8 @@
1
- import { spawn as spawnPty } from './bun-pty.ts';
2
1
  import { randomBytes } from 'node:crypto';
3
- import { Terminal } from './terminal.ts';
4
2
  import type { PtyOptions } from './bun-pty.ts';
3
+ import { spawn as spawnPty } from './bun-pty.ts';
4
+ import { Terminal } from './terminal.ts';
5
+ import { logger } from '../utils/logger.ts';
5
6
 
6
7
  const MAX_TERMINALS = 10;
7
8
  const CLEANUP_DELAY_MS = 5 * 60 * 1000;
@@ -19,10 +20,7 @@ export class TerminalManager {
19
20
  private terminals = new Map<string, Terminal>();
20
21
  private cleanupTimers = new Map<string, NodeJS.Timeout>();
21
22
 
22
- constructor() {
23
- process.on('SIGTERM', () => this.killAll());
24
- process.on('SIGINT', () => this.killAll());
25
- }
23
+ constructor() {}
26
24
 
27
25
  create(options: CreateTerminalOptions): Terminal {
28
26
  if (this.terminals.size >= MAX_TERMINALS) {
@@ -32,7 +30,7 @@ export class TerminalManager {
32
30
  const id = this.generateId();
33
31
 
34
32
  try {
35
- console.log('[TerminalManager] Creating terminal:', {
33
+ logger.debug('TerminalManager: creating terminal', {
36
34
  id,
37
35
  command: options.command,
38
36
  args: options.args,
@@ -50,7 +48,9 @@ export class TerminalManager {
50
48
 
51
49
  const pty = spawnPty(options.command, options.args || [], ptyOptions);
52
50
 
53
- console.log('[TerminalManager] PTY created successfully:', pty.pid);
51
+ logger.debug('TerminalManager: PTY created', {
52
+ pid: pty.pid,
53
+ });
54
54
 
55
55
  const terminal = new Terminal(id, pty, options);
56
56
 
@@ -64,11 +64,11 @@ export class TerminalManager {
64
64
 
65
65
  this.terminals.set(id, terminal);
66
66
 
67
- console.log('[TerminalManager] Terminal added to map');
67
+ logger.debug('TerminalManager: terminal added to map', { id });
68
68
 
69
69
  return terminal;
70
70
  } catch (error) {
71
- console.error('[TerminalManager] Failed to create terminal:', error);
71
+ logger.error('TerminalManager: failed to create terminal', error);
72
72
  throw error;
73
73
  }
74
74
  }
@@ -0,0 +1,40 @@
1
+ const TRUTHY = new Set(['1', 'true', 'yes', 'on']);
2
+
3
+ type GlobalDebugFlags = {
4
+ __AGI_DEBUG_ENABLED__?: boolean;
5
+ __AGI_TRACE_ENABLED__?: boolean;
6
+ };
7
+
8
+ function readGlobalFlag(
9
+ key: '__AGI_DEBUG_ENABLED__' | '__AGI_TRACE_ENABLED__',
10
+ ) {
11
+ const globalState = globalThis as GlobalDebugFlags;
12
+ return globalState[key];
13
+ }
14
+
15
+ function envEnabled(keys: string[]): boolean {
16
+ for (const key of keys) {
17
+ const raw = typeof process !== 'undefined' ? process.env?.[key] : undefined;
18
+ if (!raw) continue;
19
+ const trimmed = raw.trim().toLowerCase();
20
+ if (!trimmed) continue;
21
+ if (TRUTHY.has(trimmed) || trimmed === 'all') return true;
22
+ }
23
+ return false;
24
+ }
25
+
26
+ export function isDebugEnabled(): boolean {
27
+ const globalFlag = readGlobalFlag('__AGI_DEBUG_ENABLED__');
28
+ if (typeof globalFlag === 'boolean') {
29
+ return globalFlag;
30
+ }
31
+ return envEnabled(['AGI_DEBUG', 'DEBUG_AGI']);
32
+ }
33
+
34
+ export function isTraceEnabled(): boolean {
35
+ const globalFlag = readGlobalFlag('__AGI_TRACE_ENABLED__');
36
+ if (typeof globalFlag === 'boolean') {
37
+ return Boolean(globalFlag) && isDebugEnabled();
38
+ }
39
+ return envEnabled(['AGI_TRACE', 'TRACE_AGI']) && isDebugEnabled();
40
+ }
@@ -0,0 +1,150 @@
1
+ import { isDebugEnabled, isTraceEnabled } from './debug.ts';
2
+
3
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
4
+
5
+ function safeHasMeta(
6
+ meta?: Record<string, unknown>,
7
+ ): meta is Record<string, unknown> {
8
+ return Boolean(meta && Object.keys(meta).length);
9
+ }
10
+
11
+ export function debug(message: string, meta?: Record<string, unknown>): void {
12
+ if (!isDebugEnabled()) return;
13
+ try {
14
+ if (safeHasMeta(meta)) {
15
+ console.log(`[debug] ${message}`, meta);
16
+ } else {
17
+ console.log(`[debug] ${message}`);
18
+ }
19
+ } catch {
20
+ // ignore logging errors
21
+ }
22
+ }
23
+
24
+ export function info(message: string, meta?: Record<string, unknown>): void {
25
+ if (!isDebugEnabled() && !isTraceEnabled()) return;
26
+ try {
27
+ if (safeHasMeta(meta)) {
28
+ console.log(`[info] ${message}`, meta);
29
+ } else {
30
+ console.log(`[info] ${message}`);
31
+ }
32
+ } catch {
33
+ // ignore logging errors
34
+ }
35
+ }
36
+
37
+ export function warn(message: string, meta?: Record<string, unknown>): void {
38
+ try {
39
+ if (safeHasMeta(meta)) {
40
+ console.warn(`[warn] ${message}`, meta);
41
+ } else {
42
+ console.warn(`[warn] ${message}`);
43
+ }
44
+ } catch {
45
+ // ignore logging errors
46
+ }
47
+ }
48
+
49
+ export function error(
50
+ message: string,
51
+ err?: unknown,
52
+ meta?: Record<string, unknown>,
53
+ ): void {
54
+ if (!isDebugEnabled()) return;
55
+
56
+ try {
57
+ const logMeta: Record<string, unknown> = meta ? { ...meta } : {};
58
+
59
+ if (err) {
60
+ if (err instanceof Error) {
61
+ logMeta.error = {
62
+ name: err.name,
63
+ message: err.message,
64
+ };
65
+ if (isTraceEnabled() && err.stack) {
66
+ (logMeta.error as { stack?: string }).stack = err.stack;
67
+ }
68
+ } else if (typeof err === 'string') {
69
+ logMeta.error = err;
70
+ } else if (typeof err === 'object') {
71
+ const errObj = err as Record<string, unknown>;
72
+ const details: Record<string, unknown> = {};
73
+ if (typeof errObj.name === 'string') details.name = errObj.name;
74
+ if (typeof errObj.message === 'string')
75
+ details.message = errObj.message;
76
+ if (typeof errObj.code === 'string') details.code = errObj.code;
77
+ if (typeof errObj.status === 'number') details.status = errObj.status;
78
+ if (typeof errObj.statusCode === 'number')
79
+ details.statusCode = errObj.statusCode;
80
+ if (
81
+ isTraceEnabled() &&
82
+ typeof errObj.stack === 'string' &&
83
+ !details.stack
84
+ ) {
85
+ details.stack = errObj.stack;
86
+ }
87
+ logMeta.error = Object.keys(details).length ? details : errObj;
88
+ } else {
89
+ logMeta.error = String(err);
90
+ }
91
+ }
92
+
93
+ if (safeHasMeta(logMeta)) {
94
+ console.error(`[error] ${message}`, logMeta);
95
+ } else {
96
+ console.error(`[error] ${message}`);
97
+ }
98
+ } catch (logErr) {
99
+ try {
100
+ console.error(`[error] ${message} (logging failed)`, logErr);
101
+ } catch {
102
+ // ignore
103
+ }
104
+ }
105
+ }
106
+
107
+ export const logger = {
108
+ debug,
109
+ info,
110
+ warn,
111
+ error,
112
+ };
113
+
114
+ function nowMs(): number {
115
+ const perf = (globalThis as { performance?: { now?: () => number } })
116
+ .performance;
117
+ if (perf && typeof perf.now === 'function') return perf.now();
118
+ return Date.now();
119
+ }
120
+
121
+ type Timer = {
122
+ end(meta?: Record<string, unknown>): void;
123
+ };
124
+
125
+ export function time(label: string): Timer {
126
+ if (!isDebugEnabled()) {
127
+ return { end() {} };
128
+ }
129
+
130
+ const start = nowMs();
131
+ let finished = false;
132
+
133
+ return {
134
+ end(meta?: Record<string, unknown>) {
135
+ if (finished) return;
136
+ finished = true;
137
+ const duration = nowMs() - start;
138
+ try {
139
+ const base = `[timing] ${label} ${duration.toFixed(1)}ms`;
140
+ if (safeHasMeta(meta)) {
141
+ console.log(base, meta);
142
+ } else {
143
+ console.log(base);
144
+ }
145
+ } catch {
146
+ // ignore timing log errors
147
+ }
148
+ },
149
+ };
150
+ }
package/src/index.ts CHANGED
@@ -161,6 +161,18 @@ export {
161
161
  ServiceError,
162
162
  } from './core/src/index.ts';
163
163
 
164
+ // Logging & Debug
165
+ export {
166
+ logger,
167
+ debug,
168
+ info,
169
+ warn,
170
+ error,
171
+ time,
172
+ isDebugEnabled,
173
+ isTraceEnabled,
174
+ } from './core/src/index.ts';
175
+
164
176
  // Schema Validation
165
177
  export { z } from './core/src/index.ts';
166
178