sam-coder-cli 1.0.5 → 1.0.6

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/agi-cli.js CHANGED
@@ -13,7 +13,7 @@ const execAsync = util.promisify(exec);
13
13
  const CONFIG_PATH = path.join(os.homedir(), '.sam-coder-config.json');
14
14
  let OPENROUTER_API_KEY;
15
15
  const MODEL = 'deepseek/deepseek-chat-v3-0324:free';
16
- const API_BASE_URL = 'https://openrouter.ai/api/v1';
16
+ let API_BASE_URL = 'https://openrouter.ai/api/v1';
17
17
 
18
18
  // Tool/Function definitions for the AI
19
19
  const tools = [
@@ -775,8 +775,19 @@ async function runSetup(isReconfig = false) {
775
775
  }
776
776
 
777
777
  const apiKey = await askQuestion('Enter OpenRouter API Key: ');
778
+ const proCode = await askQuestion('Enter Pro Plan activation code (or press Enter to skip): ');
779
+
780
+ let config = { OPENROUTER_API_KEY: apiKey, isPro: false };
781
+
782
+ if (proCode === '1234') {
783
+ console.log('✅ Pro Plan activated!');
784
+ const customEndpoint = await askQuestion('Enter custom OpenAI-compatible API endpoint: ');
785
+ config.isPro = true;
786
+ config.customApiBase = customEndpoint;
787
+ } else if (proCode) {
788
+ console.log('⚠️ Invalid activation code. Continuing with standard setup.');
789
+ }
778
790
 
779
- const config = { OPENROUTER_API_KEY: apiKey };
780
791
  await writeConfig(config);
781
792
 
782
793
  console.log('✅ Configuration saved successfully!');
@@ -793,6 +804,10 @@ async function start() {
793
804
  }
794
805
 
795
806
  OPENROUTER_API_KEY = config.OPENROUTER_API_KEY;
807
+ if (config.isPro && config.customApiBase) {
808
+ API_BASE_URL = config.customApiBase;
809
+ console.log(`🚀 Using Pro Plan custom endpoint: ${API_BASE_URL}`);
810
+ }
796
811
 
797
812
  ui.showHeader();
798
813
  console.log('Select Mode:');
@@ -1,125 +1,218 @@
1
1
  import pygame
2
- import time
3
2
  import random
4
3
 
5
4
  # Initialize pygame
6
5
  pygame.init()
7
6
 
8
- # Screen dimensions
9
- WIDTH, HEIGHT = 800, 600
7
+ # Constants
8
+ SCREEN_WIDTH = 300
9
+ SCREEN_HEIGHT = 600
10
+ BLOCK_SIZE = 30
11
+ GRID_WIDTH = 10
12
+ GRID_HEIGHT = 20
13
+ GAME_AREA_LEFT = (SCREEN_WIDTH - GRID_WIDTH * BLOCK_SIZE) // 2
14
+ GAME_AREA_TOP = SCREEN_HEIGHT - GRID_HEIGHT * BLOCK_SIZE
10
15
 
11
16
  # Colors
12
- WHITE = (255, 255, 255)
13
17
  BLACK = (0, 0, 0)
14
- RED = (213, 50, 80)
15
- GREEN = (0, 255, 0)
16
- BLUE = (50, 153, 213)
17
-
18
- # Snake block size
19
- BLOCK_SIZE = 20
18
+ WHITE = (255, 255, 255)
19
+ GRAY = (128, 128, 128)
20
+ COLORS = [
21
+ (0, 255, 255), # Cyan (I)
22
+ (0, 0, 255), # Blue (J)
23
+ (255, 165, 0), # Orange (L)
24
+ (255, 255, 0), # Yellow (O)
25
+ (0, 255, 0), # Green (S)
26
+ (128, 0, 128), # Purple (T)
27
+ (255, 0, 0) # Red (Z)
28
+ ]
29
+
30
+ # Tetrimino shapes
31
+ SHAPES = [
32
+ [[1, 1, 1, 1]], # I
33
+ [[1, 0, 0], [1, 1, 1]], # J
34
+ [[0, 0, 1], [1, 1, 1]], # L
35
+ [[1, 1], [1, 1]], # O
36
+ [[0, 1, 1], [1, 1, 0]], # S
37
+ [[0, 1, 0], [1, 1, 1]], # T
38
+ [[1, 1, 0], [0, 1, 1]] # Z
39
+ ]
40
+
41
+ # Set up the display
42
+ screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
43
+ pygame.display.set_caption("Tetris")
20
44
 
21
- # Clock for controlling the speed of the snake
22
45
  clock = pygame.time.Clock()
23
46
 
24
- # Font for score
25
- font_style = pygame.font.SysFont("bahnschrift", 25)
26
- score_font = pygame.font.SysFont("comicsansms", 35)
27
-
28
- def message(msg, color):
29
- mesg = font_style.render(msg, True, color)
30
- screen.blit(mesg, [WIDTH / 6, HEIGHT / 3])
31
-
32
- def your_score(score):
33
- value = score_font.render("Your Score: " + str(score), True, GREEN)
34
- screen.blit(value, [0, 0])
35
-
36
- def our_snake(block_size, snake_list):
37
- for pos in snake_list:
38
- pygame.draw.rect(screen, BLUE, [pos[0], pos[1], block_size, block_size])
39
-
40
- def gameLoop():
41
- game_over = False
42
- game_close = False
43
-
44
- x1 = WIDTH / 2
45
- y1 = HEIGHT / 2
46
-
47
- x1_change = 0
48
- y1_change = 0
49
-
50
- snake_list = []
51
- length_of_snake = 1
52
-
53
- foodx = round(random.randrange(0, WIDTH - BLOCK_SIZE) / 20.0) * 20.0
54
- foody = round(random.randrange(0, HEIGHT - BLOCK_SIZE) / 20.0) * 20.0
55
-
56
- while not game_over:
57
-
58
- while game_close:
59
- screen.fill(BLACK)
60
- message("You Lost! Press Q-Quit or C-Play Again", RED)
61
- your_score(length_of_snake - 1)
62
- pygame.display.update()
63
-
64
- for event in pygame.event.get():
65
- if event.type == pygame.KEYDOWN:
66
- if event.key == pygame.K_q:
67
- game_over = True
68
- game_close = False
69
- if event.key == pygame.K_c:
70
- gameLoop()
71
-
72
- for event in pygame.event.get():
73
- if event.type == pygame.QUIT:
47
+ # Game variables
48
+ grid = [[0 for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
49
+ current_piece = None
50
+ next_piece = None
51
+ current_x = GRID_WIDTH // 2
52
+ current_y = 0
53
+ score = 0
54
+ game_over = False
55
+ fall_time = 0
56
+ fall_speed = 0.5 # seconds
57
+
58
+ def new_piece():
59
+ global current_piece, next_piece, current_x, current_y
60
+ if next_piece is None:
61
+ next_piece = random.randint(0, len(SHAPES) - 1)
62
+ current_piece = next_piece
63
+ next_piece = random.randint(0, len(SHAPES) - 1)
64
+ current_x = GRID_WIDTH // 2 - len(SHAPES[current_piece][0]) // 2
65
+ current_y = 0
66
+ if check_collision():
67
+ return False
68
+ return True
69
+
70
+ def check_collision():
71
+ for y, row in enumerate(SHAPES[current_piece]):
72
+ for x, cell in enumerate(row):
73
+ if cell:
74
+ if (current_y + y >= GRID_HEIGHT or
75
+ current_x + x < 0 or
76
+ current_x + x >= GRID_WIDTH or
77
+ grid[current_y + y][current_x + x]):
78
+ return True
79
+ return False
80
+
81
+ def merge_piece():
82
+ for y, row in enumerate(SHAPES[current_piece]):
83
+ for x, cell in enumerate(row):
84
+ if cell:
85
+ grid[current_y + y][current_x + x] = current_piece + 1
86
+
87
+ def clear_lines():
88
+ global grid, score
89
+ lines_cleared = 0
90
+ for y in range(GRID_HEIGHT - 1, -1, -1):
91
+ if all(grid[y]):
92
+ lines_cleared += 1
93
+ for y2 in range(y, 0, -1):
94
+ grid[y2] = grid[y2 - 1][:]
95
+ grid[0] = [0] * GRID_WIDTH
96
+ score += lines_cleared ** 2 * 100
97
+
98
+ def draw_grid():
99
+ for y in range(GRID_HEIGHT):
100
+ for x in range(GRID_WIDTH):
101
+ if grid[y][x]:
102
+ pygame.draw.rect(
103
+ screen, COLORS[grid[y][x] - 1],
104
+ (GAME_AREA_LEFT + x * BLOCK_SIZE, GAME_AREA_TOP + y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
105
+ )
106
+ pygame.draw.rect(
107
+ screen, WHITE,
108
+ (GAME_AREA_LEFT + x * BLOCK_SIZE, GAME_AREA_TOP + y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE),
109
+ 1
110
+ )
111
+
112
+ def draw_piece():
113
+ for y, row in enumerate(SHAPES[current_piece]):
114
+ for x, cell in enumerate(row):
115
+ if cell:
116
+ pygame.draw.rect(
117
+ screen, COLORS[current_piece],
118
+ (GAME_AREA_LEFT + (current_x + x) * BLOCK_SIZE, GAME_AREA_TOP + (current_y + y) * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
119
+ )
120
+ pygame.draw.rect(
121
+ screen, WHITE,
122
+ (GAME_AREA_LEFT + (current_x + x) * BLOCK_SIZE, GAME_AREA_TOP + (current_y + y) * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE),
123
+ 1
124
+ )
125
+
126
+ def draw_next_piece():
127
+ if next_piece is not None:
128
+ font = pygame.font.SysFont(None, 24)
129
+ text = font.render("Next:", True, WHITE)
130
+ screen.blit(text, (20, 20))
131
+ for y, row in enumerate(SHAPES[next_piece]):
132
+ for x, cell in enumerate(row):
133
+ if cell:
134
+ pygame.draw.rect(
135
+ screen, COLORS[next_piece],
136
+ (40 + x * BLOCK_SIZE, 50 + y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE)
137
+ )
138
+ pygame.draw.rect(
139
+ screen, WHITE,
140
+ (40 + x * BLOCK_SIZE, 50 + y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE),
141
+ 1
142
+ )
143
+
144
+ def draw_score():
145
+ font = pygame.font.SysFont(None, 36)
146
+ text = font.render(f"Score: {score}", True, WHITE)
147
+ screen.blit(text, (20, SCREEN_HEIGHT - 50))
148
+
149
+ def rotate_piece():
150
+ global current_piece
151
+ rotated = list(zip(*reversed(SHAPES[current_piece])))
152
+ for y in range(len(rotated)):
153
+ rotated[y] = list(rotated[y])
154
+ old_shape = SHAPES[current_piece]
155
+ SHAPES[current_piece] = rotated
156
+ if check_collision():
157
+ SHAPES[current_piece] = old_shape
158
+
159
+ # Main game loop
160
+ new_piece()
161
+ running = True
162
+ while running:
163
+ screen.fill(BLACK)
164
+ fall_time += clock.get_rawtime() / 1000 # Convert to seconds
165
+ clock.tick()
166
+
167
+ if fall_time >= fall_speed:
168
+ fall_time = 0
169
+ current_y += 1
170
+ if check_collision():
171
+ current_y -= 1
172
+ merge_piece()
173
+ clear_lines()
174
+ if not new_piece():
74
175
  game_over = True
75
- if event.type == pygame.KEYDOWN:
76
- if event.key == pygame.K_LEFT:
77
- x1_change = -BLOCK_SIZE
78
- y1_change = 0
79
- elif event.key == pygame.K_RIGHT:
80
- x1_change = BLOCK_SIZE
81
- y1_change = 0
82
- elif event.key == pygame.K_UP:
83
- y1_change = -BLOCK_SIZE
84
- x1_change = 0
85
- elif event.key == pygame.K_DOWN:
86
- y1_change = BLOCK_SIZE
87
- x1_change = 0
88
-
89
- if x1 >= WIDTH or x1 < 0 or y1 >= HEIGHT or y1 < 0:
90
- game_close = True
91
- x1 += x1_change
92
- y1 += y1_change
93
- screen.fill(BLACK)
94
- pygame.draw.rect(screen, GREEN, [foodx, foody, BLOCK_SIZE, BLOCK_SIZE])
95
- snake_head = []
96
- snake_head.append(x1)
97
- snake_head.append(y1)
98
- snake_list.append(snake_head)
99
- if len(snake_list) > length_of_snake:
100
- del snake_list[0]
101
-
102
- for pos in snake_list[:-1]:
103
- if pos == snake_head:
104
- game_close = True
105
-
106
- our_snake(BLOCK_SIZE, snake_list)
107
- your_score(length_of_snake - 1)
108
176
 
177
+ for event in pygame.event.get():
178
+ if event.type == pygame.QUIT:
179
+ running = False
180
+ if event.type == pygame.KEYDOWN:
181
+ if event.key == pygame.K_LEFT:
182
+ current_x -= 1
183
+ if check_collision():
184
+ current_x += 1
185
+ if event.key == pygame.K_RIGHT:
186
+ current_x += 1
187
+ if check_collision():
188
+ current_x -= 1
189
+ if event.key == pygame.K_DOWN:
190
+ current_y += 1
191
+ if check_collision():
192
+ current_y -= 1
193
+ if event.key == pygame.K_UP:
194
+ rotate_piece()
195
+ if event.key == pygame.K_SPACE:
196
+ while not check_collision():
197
+ current_y += 1
198
+ current_y -= 1
199
+ merge_piece()
200
+ clear_lines()
201
+ if not new_piece():
202
+ game_over = True
203
+
204
+ draw_grid()
205
+ draw_piece()
206
+ draw_next_piece()
207
+ draw_score()
208
+ pygame.display.update()
209
+
210
+ if game_over:
211
+ font = pygame.font.SysFont(None, 48)
212
+ text = font.render("GAME OVER", True, WHITE)
213
+ screen.blit(text, (SCREEN_WIDTH // 2 - 100, SCREEN_HEIGHT // 2 - 24))
109
214
  pygame.display.update()
215
+ pygame.time.wait(2000)
216
+ running = False
110
217
 
111
- if x1 == foodx and y1 == foody:
112
- foodx = round(random.randrange(0, WIDTH - BLOCK_SIZE) / 20.0) * 20.0
113
- foody = round(random.randrange(0, HEIGHT - BLOCK_SIZE) / 20.0) * 20.0
114
- length_of_snake += 1
115
-
116
- clock.tick(15)
117
-
118
- pygame.quit()
119
- quit()
120
-
121
- # Create the screen
122
- screen = pygame.display.set_mode((WIDTH, HEIGHT))
123
- pygame.display.set_caption('Snake Game')
124
-
125
- gameLoop()
218
+ pygame.quit()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sam-coder-cli",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "SAM-CODER: An animated command-line AI assistant with agency capabilities.",
5
5
  "main": "bin/agi-cli.js",
6
6
  "bin": {