@clawlabz/clawskin 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawlabz/clawskin",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "type": "module",
5
5
  "description": "Pixel Agent Skin Engine \u2014 Procedural 32\u00d732 character generator with scenes, animations & customization",
6
6
  "keywords": [
package/public/app.html CHANGED
@@ -319,11 +319,16 @@
319
319
  let app, editingSlot = null;
320
320
 
321
321
  // ── Fullscreen canvas sizing ──
322
+ // Fixed logical resolution — CSS scales it up with pixelated rendering.
323
+ // This keeps pixel characters proportional on any screen size.
324
+ const LOGICAL_W = 960;
325
+ const LOGICAL_H = 600;
326
+
322
327
  function resizeCanvas() {
323
328
  const c = document.getElementById('app-canvas');
324
- c.width = window.innerWidth;
325
- c.height = window.innerHeight;
326
- if (app) { app.width = c.width; app.height = c.height; }
329
+ c.width = LOGICAL_W;
330
+ c.height = LOGICAL_H;
331
+ if (app) { app.width = LOGICAL_W; app.height = LOGICAL_H; }
327
332
  }
328
333
  window.addEventListener('resize', resizeCanvas);
329
334
  resizeCanvas();
@@ -533,8 +538,8 @@
533
538
  document.addEventListener('DOMContentLoaded', () => {
534
539
  try {
535
540
  app = new ClawSkinApp('app-canvas', {
536
- width: window.innerWidth,
537
- height: window.innerHeight,
541
+ width: LOGICAL_W,
542
+ height: LOGICAL_H,
538
543
  });
539
544
  app.init();
540
545
  window._app = app;
@@ -170,15 +170,17 @@ class ClawSkinApp {
170
170
  const config = await res.json();
171
171
  if (config?.gatewayUrl) {
172
172
  const saved = this.settings.load();
173
+ const token = config.token || saved.token || '';
174
+ this._configAgents = config.agents || [];
173
175
  this.settings.update({
174
176
  gatewayUrl: config.gatewayUrl,
177
+ token: token,
175
178
  autoConnect: true,
176
179
  });
177
180
  if (window._connPanel) {
178
181
  window._connPanel.render(this.settings.load());
179
182
  }
180
- // Use previously saved token if available; never read token from /api/config
181
- this.gateway.connect(config.gatewayUrl, saved.token || '');
183
+ this.gateway.connect(config.gatewayUrl, token);
182
184
  return;
183
185
  }
184
186
  }
@@ -265,55 +267,62 @@ class ClawSkinApp {
265
267
  // ──── Multi-Agent Management ────
266
268
 
267
269
  async _discoverAgents() {
270
+ // Start with agents from config file (all agents, regardless of activity)
271
+ const configAgents = this._configAgents || [];
272
+ const knownAgentIds = new Set();
273
+
274
+ // Phase 1: Create slots for all agents from config file
275
+ for (const agent of configAgents) {
276
+ if (!agent.id) continue;
277
+ knownAgentIds.add(agent.id);
278
+ this._addAgent({
279
+ agentId: agent.id,
280
+ name: agent.name || agent.id,
281
+ label: agent.name || agent.id,
282
+ sessionKeys: [],
283
+ });
284
+ }
285
+
286
+ // Phase 2: Discover active sessions from Gateway and attach to slots
268
287
  try {
269
288
  const result = await this.gateway.getSessionsList({ activeMinutes: 1440 });
270
289
  const sessions = result?.sessions || result || [];
271
290
 
272
- if (!Array.isArray(sessions) || sessions.length === 0) {
273
- this._addAgent({ agentId: 'main', label: 'Main Agent', sessionKeys: ['main'] });
274
- return;
275
- }
276
-
277
- // Group sessions by agentId
278
- // Session keys look like: "agent:main:main", "agent:ifig:discord:channel:123", "agent:xhs:main"
279
- // The agentId is either session.agentId or extracted from the key pattern "agent:<agentId>:..."
280
- const agentMap = new Map();
291
+ if (Array.isArray(sessions)) {
292
+ for (const session of sessions) {
293
+ const key = session.key || session.sessionKey;
294
+ if (!key) continue;
281
295
 
282
- for (const session of sessions) {
283
- const key = session.key || session.sessionKey;
284
- if (!key) continue;
285
-
286
- // Determine agentId: prefer session.agentId, else parse from key
287
- let agentId = session.agentId || null;
288
- if (!agentId) {
289
- const match = key.match(/^agent:([^:]+):/);
290
- agentId = match ? match[1] : 'main';
291
- }
296
+ let agentId = session.agentId || null;
297
+ if (!agentId) {
298
+ const match = key.match(/^agent:([^:]+):/);
299
+ agentId = match ? match[1] : 'main';
300
+ }
292
301
 
293
- if (!agentMap.has(agentId)) {
294
- agentMap.set(agentId, {
295
- agentId,
296
- label: session.label || agentId,
297
- sessionKeys: [],
298
- });
302
+ // If this agent wasn't in config, create a slot for it
303
+ if (!knownAgentIds.has(agentId)) {
304
+ knownAgentIds.add(agentId);
305
+ this._addAgent({
306
+ agentId,
307
+ label: session.label || agentId,
308
+ sessionKeys: [key],
309
+ });
310
+ } else {
311
+ // Attach session key to existing slot
312
+ const slot = this.agents.find(a => a.agentId === agentId);
313
+ if (slot && !slot.sessionKeys.includes(key)) {
314
+ slot.sessionKeys.push(key);
315
+ slot.stateMapper.addSessionKey(key);
316
+ }
317
+ }
299
318
  }
300
- agentMap.get(agentId).sessionKeys.push(key);
301
- }
302
-
303
- // Create one AgentSlot per unique agentId
304
- for (const [agentId, info] of agentMap) {
305
- this._addAgent({
306
- agentId,
307
- label: info.label,
308
- sessionKeys: info.sessionKeys,
309
- });
310
- }
311
-
312
- if (this.agents.length === 0) {
313
- this._addAgent({ agentId: 'main', label: 'Main Agent', sessionKeys: ['main'] });
314
319
  }
315
320
  } catch (e) {
316
321
  console.warn('[ClawSkinApp] session discovery failed:', e);
322
+ }
323
+
324
+ // Phase 3: Fallback — ensure at least one agent exists
325
+ if (this.agents.length === 0) {
317
326
  this._addAgent({ agentId: 'main', label: 'Main Agent', sessionKeys: ['main'] });
318
327
  }
319
328
 
package/serve.cjs CHANGED
@@ -44,11 +44,16 @@ function getLocalGatewayConfig() {
44
44
  const config = JSON.parse(raw);
45
45
  const gw = config.gateway || {};
46
46
  const port = gw.port || 18789;
47
+ const agentsList = (config.agents?.list || []).map(a => ({
48
+ id: a.id,
49
+ name: a.identity?.name || a.name || a.id,
50
+ }));
47
51
  return {
48
52
  gatewayUrl: `ws://localhost:${port}`,
49
- // Only expose that auth is token-based, never send the actual token.
50
- // The user must enter the token manually in the UI.
51
- hasAuth: !!(gw.auth && gw.auth.mode === 'token'),
53
+ // Safe to expose token on localhost serve.cjs binds to 127.0.0.1 by default.
54
+ // The token never leaves the local machine.
55
+ token: (gw.auth && gw.auth.token) || '',
56
+ agents: agentsList,
52
57
  };
53
58
  } catch { continue; }
54
59
  }