@clawlabz/clawskin 1.0.1 → 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.1",
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,16 @@ 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 token from local config, fall back to previously saved token
181
- const token = config.token || saved.token || '';
182
183
  this.gateway.connect(config.gatewayUrl, token);
183
184
  return;
184
185
  }
@@ -266,55 +267,62 @@ class ClawSkinApp {
266
267
  // ──── Multi-Agent Management ────
267
268
 
268
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
269
287
  try {
270
288
  const result = await this.gateway.getSessionsList({ activeMinutes: 1440 });
271
289
  const sessions = result?.sessions || result || [];
272
290
 
273
- if (!Array.isArray(sessions) || sessions.length === 0) {
274
- this._addAgent({ agentId: 'main', label: 'Main Agent', sessionKeys: ['main'] });
275
- return;
276
- }
277
-
278
- // Group sessions by agentId
279
- // Session keys look like: "agent:main:main", "agent:ifig:discord:channel:123", "agent:xhs:main"
280
- // The agentId is either session.agentId or extracted from the key pattern "agent:<agentId>:..."
281
- const agentMap = new Map();
282
-
283
- for (const session of sessions) {
284
- const key = session.key || session.sessionKey;
285
- if (!key) continue;
291
+ if (Array.isArray(sessions)) {
292
+ for (const session of sessions) {
293
+ const key = session.key || session.sessionKey;
294
+ if (!key) continue;
286
295
 
287
- // Determine agentId: prefer session.agentId, else parse from key
288
- let agentId = session.agentId || null;
289
- if (!agentId) {
290
- const match = key.match(/^agent:([^:]+):/);
291
- agentId = match ? match[1] : 'main';
292
- }
296
+ let agentId = session.agentId || null;
297
+ if (!agentId) {
298
+ const match = key.match(/^agent:([^:]+):/);
299
+ agentId = match ? match[1] : 'main';
300
+ }
293
301
 
294
- if (!agentMap.has(agentId)) {
295
- agentMap.set(agentId, {
296
- agentId,
297
- label: session.label || agentId,
298
- sessionKeys: [],
299
- });
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
+ }
300
318
  }
301
- agentMap.get(agentId).sessionKeys.push(key);
302
- }
303
-
304
- // Create one AgentSlot per unique agentId
305
- for (const [agentId, info] of agentMap) {
306
- this._addAgent({
307
- agentId,
308
- label: info.label,
309
- sessionKeys: info.sessionKeys,
310
- });
311
- }
312
-
313
- if (this.agents.length === 0) {
314
- this._addAgent({ agentId: 'main', label: 'Main Agent', sessionKeys: ['main'] });
315
319
  }
316
320
  } catch (e) {
317
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) {
318
326
  this._addAgent({ agentId: 'main', label: 'Main Agent', sessionKeys: ['main'] });
319
327
  }
320
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
53
  // Safe to expose token on localhost — serve.cjs binds to 127.0.0.1 by default.
50
54
  // The token never leaves the local machine.
51
55
  token: (gw.auth && gw.auth.token) || '',
56
+ agents: agentsList,
52
57
  };
53
58
  } catch { continue; }
54
59
  }