conectese 0.1.15 → 0.2.0

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.
Files changed (168) hide show
  1. package/README.md +2 -2
  2. package/agents/conectese_admin/AGENT.md +10 -5
  3. package/agents/data-extractor/AGENT.md +35 -3
  4. package/agents/direito-administrativo/AGENT.md +68 -22
  5. package/agents/direito-aduaneiro/AGENT.md +55 -0
  6. package/agents/direito-aeroportuario/AGENT.md +53 -0
  7. package/agents/direito-agrario/AGENT.md +73 -0
  8. package/agents/direito-ambiental/AGENT.md +61 -24
  9. package/agents/direito-bancario/AGENT.md +79 -0
  10. package/agents/direito-civil/AGENT.md +71 -20
  11. package/agents/direito-constitucional/AGENT.md +79 -0
  12. package/agents/direito-da-crianca-e-do-adolescente-eca/AGENT.md +69 -0
  13. package/agents/direito-da-propriedade-intelectual/AGENT.md +65 -0
  14. package/agents/direito-de-familia/AGENT.md +92 -0
  15. package/agents/direito-de-transito/AGENT.md +59 -0
  16. package/agents/direito-desportivo/AGENT.md +40 -27
  17. package/agents/direito-digital/AGENT.md +61 -24
  18. package/agents/direito-do-consumidor/AGENT.md +77 -0
  19. package/agents/direito-do-trabalho/AGENT.md +73 -20
  20. package/agents/direito-economico/AGENT.md +58 -0
  21. package/agents/direito-eleitoral/AGENT.md +56 -24
  22. package/agents/direito-empresarial/AGENT.md +62 -24
  23. package/agents/direito-financeiro/AGENT.md +63 -0
  24. package/agents/direito-imobiliario/AGENT.md +79 -0
  25. package/agents/direito-indigena/AGENT.md +72 -0
  26. package/agents/direito-internacional/AGENT.md +55 -24
  27. package/agents/direito-maritimo/AGENT.md +55 -0
  28. package/agents/direito-medico-e-da-saude/AGENT.md +69 -0
  29. package/agents/direito-militar/AGENT.md +54 -24
  30. package/agents/direito-notarial-e-registral/AGENT.md +47 -24
  31. package/agents/direito-penal/AGENT.md +74 -19
  32. package/agents/direito-previdenciario/AGENT.md +84 -0
  33. package/agents/direito-processal-civil/AGENT.md +72 -20
  34. package/agents/direito-processal-do-trabalho/AGENT.md +58 -24
  35. package/agents/direito-processal-militar/AGENT.md +38 -27
  36. package/agents/direito-processal-penal/AGENT.md +62 -24
  37. package/agents/direito-processual-civil/AGENT.md +94 -0
  38. package/agents/direito-processual-do-trabalho/AGENT.md +76 -0
  39. package/agents/direito-processual-militar/AGENT.md +53 -0
  40. package/agents/direito-processual-penal/AGENT.md +80 -0
  41. package/agents/direito-securitario/AGENT.md +75 -0
  42. package/agents/direito-sindical/AGENT.md +46 -24
  43. package/agents/direito-societario/AGENT.md +65 -0
  44. package/agents/direito-tributario/AGENT.md +98 -0
  45. package/agents/direito-urbanistico/AGENT.md +58 -0
  46. package/agents/direitos-humanos/AGENT.md +76 -0
  47. package/agents/legal-analyst/AGENT.md +1 -1
  48. package/agents/legal-designer/AGENT.md +8 -3
  49. package/agents/lgpd-anonymizer/AGENT.md +66 -4
  50. package/agents/lgpd-restorer/AGENT.md +38 -4
  51. package/agents/task-router/AGENT.md +47 -3
  52. package/bin/conectese.js +4 -4
  53. package/dashboard/src/App.tsx +6 -4
  54. package/dashboard/src/components/CheckpointModal.tsx +150 -0
  55. package/dashboard/src/components/StatusBadge.tsx +3 -3
  56. package/dashboard/src/components/StatusBar.tsx +7 -7
  57. package/dashboard/src/components/{SquadCard.tsx → TeamCard.tsx} +7 -7
  58. package/dashboard/src/components/{SquadSelector.tsx → TeamSelector.tsx} +18 -18
  59. package/dashboard/src/hooks/{useSquadSocket.ts → useTeamSocket.ts} +13 -13
  60. package/dashboard/src/lib/normalizeState.ts +3 -3
  61. package/dashboard/src/office/OfficeScene.ts +3 -3
  62. package/dashboard/src/office/PhaserGame.tsx +6 -6
  63. package/dashboard/src/plugin/{squadWatcher.ts → teamWatcher.ts} +83 -44
  64. package/dashboard/src/store/useTeamStore.ts +56 -0
  65. package/dashboard/src/types/state.ts +10 -9
  66. package/dashboard/tsconfig.tsbuildinfo +1 -1
  67. package/dashboard/vite.config.ts +2 -2
  68. package/package.json +12 -9
  69. package/skills/README.md +1 -1
  70. package/skills/conectese-agent-creator/SKILL.md +1 -1
  71. package/skills/conectese-design/SKILL.md +50 -0
  72. package/skills/conectese-skill-creator/SKILL.md +3 -3
  73. package/skills/conectese-skill-creator/references/skill-format.md +4 -4
  74. package/skills/document-analyzer/SKILL.md +40 -0
  75. package/skills/document-analyzer/scripts/parse-doc.js +113 -0
  76. package/skills/image-ai-generator/SKILL.md +5 -5
  77. package/skills/image-creator/SKILL.md +3 -3
  78. package/skills/image-fetcher/SKILL.md +5 -5
  79. package/skills/instagram-publisher/SKILL.md +2 -2
  80. package/skills/jurisprudencia-validator/SKILL.md +45 -0
  81. package/skills/jurisprudencia-validator/scripts/validate-urls.js +103 -0
  82. package/skills/legal-pricing/SKILL.md +33 -0
  83. package/skills/legal-pricing/scripts/pricing-engine.js +72 -0
  84. package/skills/resend/SKILL.md +2 -2
  85. package/skills/template-designer/SKILL.md +29 -29
  86. package/src/agents-cli.js +1 -1
  87. package/src/agents.js +1 -1
  88. package/src/init.js +2 -1
  89. package/src/locales/en.json +2 -2
  90. package/src/locales/es.json +2 -2
  91. package/src/locales/pt-BR.json +2 -2
  92. package/src/readme/README.md +26 -26
  93. package/src/runs.js +14 -14
  94. package/src/skills-cli.js +1 -1
  95. package/src/update.js +1 -1
  96. package/templates/_conectese/.conectese-version +1 -1
  97. package/templates/ide-templates/antigravity/.agent/rules/conectese.md +10 -10
  98. package/templates/ide-templates/antigravity/.agent/workflows/conectese.md +18 -18
  99. package/templates/ide-templates/claude-code/.claude/skills/conectese/SKILL.md +31 -31
  100. package/templates/ide-templates/claude-code/CLAUDE.md +10 -10
  101. package/templates/ide-templates/codex/.agents/skills/conectese/SKILL.md +1 -1
  102. package/templates/ide-templates/codex/AGENTS.md +18 -18
  103. package/templates/ide-templates/cursor/.cursor/commands/conectese.md +1 -1
  104. package/templates/ide-templates/opencode/.opencode/commands/conectese.md +1 -1
  105. package/templates/ide-templates/opencode/AGENTS.md +18 -18
  106. package/templates/ide-templates/vscode-copilot/.github/prompts/conectese.prompt.md +33 -33
  107. package/_conectese/.conectese-version +0 -1
  108. package/_conectese/_memory/company/modelo_contrato.md +0 -18
  109. package/_conectese/_memory/company/modelo_procuracao.md +0 -15
  110. package/_conectese/_memory/company/modelo_recibo.md +0 -13
  111. package/_conectese/config/playwright.config.json +0 -11
  112. package/_conectese/core/architect.agent.yaml +0 -110
  113. package/_conectese/core/best-practices/_catalog.yaml +0 -116
  114. package/_conectese/core/best-practices/blog-post.md +0 -132
  115. package/_conectese/core/best-practices/blog-seo.md +0 -127
  116. package/_conectese/core/best-practices/copywriting.md +0 -426
  117. package/_conectese/core/best-practices/data-analysis.md +0 -401
  118. package/_conectese/core/best-practices/email-newsletter.md +0 -118
  119. package/_conectese/core/best-practices/email-sales.md +0 -110
  120. package/_conectese/core/best-practices/image-design.md +0 -348
  121. package/_conectese/core/best-practices/instagram-feed.md +0 -235
  122. package/_conectese/core/best-practices/instagram-reels.md +0 -112
  123. package/_conectese/core/best-practices/instagram-stories.md +0 -107
  124. package/_conectese/core/best-practices/linkedin-article.md +0 -116
  125. package/_conectese/core/best-practices/linkedin-post.md +0 -121
  126. package/_conectese/core/best-practices/researching.md +0 -349
  127. package/_conectese/core/best-practices/review.md +0 -269
  128. package/_conectese/core/best-practices/social-networks-publishing.md +0 -294
  129. package/_conectese/core/best-practices/strategist.md +0 -344
  130. package/_conectese/core/best-practices/technical-writing.md +0 -365
  131. package/_conectese/core/best-practices/twitter-post.md +0 -105
  132. package/_conectese/core/best-practices/twitter-thread.md +0 -122
  133. package/_conectese/core/best-practices/whatsapp-broadcast.md +0 -107
  134. package/_conectese/core/best-practices/youtube-script.md +0 -122
  135. package/_conectese/core/best-practices/youtube-shorts.md +0 -112
  136. package/_conectese/core/prompts/build.prompt.md +0 -547
  137. package/_conectese/core/prompts/design.prompt.md +0 -469
  138. package/_conectese/core/prompts/discovery.prompt.md +0 -269
  139. package/_conectese/core/prompts/sherlock-instagram.md +0 -123
  140. package/_conectese/core/prompts/sherlock-linkedin.md +0 -73
  141. package/_conectese/core/prompts/sherlock-shared.md +0 -684
  142. package/_conectese/core/prompts/sherlock-twitter.md +0 -78
  143. package/_conectese/core/prompts/sherlock-youtube.md +0 -85
  144. package/_conectese/core/runner.pipeline.md +0 -535
  145. package/_conectese/core/skills.engine.md +0 -381
  146. package/agents/direito-adaneiro/AGENT.md +0 -42
  147. package/agents/direito-aeroporta-rio/AGENT.md +0 -42
  148. package/agents/direito-agra-rio/AGENT.md +0 -42
  149. package/agents/direito-banca-rio/AGENT.md +0 -42
  150. package/agents/direito-constitcional/AGENT.md +0 -42
  151. package/agents/direito-da-crianc-a-e-do-adolescente-eca/AGENT.md +0 -42
  152. package/agents/direito-da-propriedade-intelectal/AGENT.md +0 -42
  153. package/agents/direito-de-ami-lia/AGENT.md +0 -42
  154. package/agents/direito-de-tra-nsito/AGENT.md +0 -42
  155. package/agents/direito-do-consmidor/AGENT.md +0 -42
  156. package/agents/direito-econo-mico/AGENT.md +0 -42
  157. package/agents/direito-imobilia-rio/AGENT.md +0 -42
  158. package/agents/direito-inanceiro/AGENT.md +0 -42
  159. package/agents/direito-mari-timo/AGENT.md +0 -42
  160. package/agents/direito-me-dico-e-da-sa-de/AGENT.md +0 -42
  161. package/agents/direito-ndia-rio/AGENT.md +0 -42
  162. package/agents/direito-previdencia-rio/AGENT.md +0 -42
  163. package/agents/direito-rbani-stico/AGENT.md +0 -42
  164. package/agents/direito-secrita-rio/AGENT.md +0 -42
  165. package/agents/direito-societa-rio/AGENT.md +0 -42
  166. package/agents/direito-tribta-rio/AGENT.md +0 -42
  167. package/agents/direitos-hmanos/AGENT.md +0 -42
  168. package/dashboard/src/store/useSquadStore.ts +0 -56
package/bin/conectese.js CHANGED
@@ -47,8 +47,8 @@ if (command === 'init') {
47
47
  const result = await agentsCli(subcommand, args, process.cwd());
48
48
  if (!result.success) process.exitCode = 1;
49
49
  } else if (command === 'runs') {
50
- const squadName = positionals[1] || null;
51
- const runs = await listRuns(squadName, process.cwd());
50
+ const teamName = positionals[1] || null;
51
+ const runs = await listRuns(teamName, process.cwd());
52
52
  printRuns(runs);
53
53
  } else {
54
54
  console.log(`
@@ -65,9 +65,9 @@ if (command === 'init') {
65
65
  npx conectese agents install <name> Install a predefined agent
66
66
  npx conectese agents remove <name> Remove an agent
67
67
  npx conectese agents update Update all agents
68
- npx conectese runs [squad-name] View execution history
68
+ npx conectese runs [team-name] View execution history
69
69
 
70
- Learn more: https://github.com/renatoasse/conectese
70
+ Learn more: https://github.com/henriqueadm-ai/conectese
71
71
  `);
72
72
  if (command) process.exitCode = 1;
73
73
  }
@@ -1,12 +1,13 @@
1
- import { useSquadSocket } from "@/hooks/useSquadSocket";
2
- import { SquadSelector } from "@/components/SquadSelector";
1
+ import { useTeamSocket } from "@/hooks/useTeamSocket";
2
+ import { TeamSelector } from "@/components/TeamSelector";
3
3
  import { PhaserGame } from "@/office/PhaserGame";
4
4
  import { StatusBar } from "@/components/StatusBar";
5
5
  import { IngestionModal } from "@/components/IngestionModal";
6
+ import { CheckpointModal } from "@/components/CheckpointModal";
6
7
  import { useState } from "react";
7
8
 
8
9
  export function App() {
9
- useSquadSocket();
10
+ useTeamSocket();
10
11
  const [showIngestion, setShowIngestion] = useState(false);
11
12
 
12
13
  return (
@@ -74,7 +75,7 @@ export function App() {
74
75
 
75
76
  {/* Main content */}
76
77
  <div style={{ display: "flex", flex: 1, overflow: "hidden" }}>
77
- <SquadSelector />
78
+ <TeamSelector />
78
79
  <PhaserGame />
79
80
  </div>
80
81
 
@@ -83,6 +84,7 @@ export function App() {
83
84
 
84
85
  {/* Overlays */}
85
86
  {showIngestion && <IngestionModal onClose={() => setShowIngestion(false)} />}
87
+ <CheckpointModal />
86
88
  </div>
87
89
  );
88
90
  }
@@ -0,0 +1,150 @@
1
+ import { useState, useEffect } from "react";
2
+ import { useTeamStore } from "@/store/useTeamStore";
3
+
4
+ export function CheckpointModal() {
5
+ const selectedTeam = useTeamStore((s) => s.selectedTeam);
6
+ const state = useTeamStore((s) =>
7
+ s.selectedTeam ? s.activeStates.get(s.selectedTeam) : undefined
8
+ );
9
+
10
+ const [formData, setFormData] = useState<Record<string, string>>({});
11
+ const [submitting, setSubmitting] = useState(false);
12
+ const [error, setError] = useState("");
13
+
14
+ const isActive = state?.status === "checkpoint" && state.handoff?.missingData && state.handoff.missingData.length > 0;
15
+ const missingFields = state?.handoff?.missingData || [];
16
+
17
+ // Reset form when checkpoint fields change
18
+ useEffect(() => {
19
+ if (isActive) {
20
+ const initial: Record<string, string> = {};
21
+ missingFields.forEach(f => initial[f] = "");
22
+ setFormData(initial);
23
+ setError("");
24
+ }
25
+ }, [isActive, missingFields.join(",")]);
26
+
27
+ if (!isActive) return null;
28
+
29
+ const handleSubmit = async (e: React.FormEvent) => {
30
+ e.preventDefault();
31
+ if (!selectedTeam) return;
32
+
33
+ // Build payload ensuring numbers where appropriate
34
+ const payload: Record<string, string | number> = {};
35
+ for (const [key, val] of Object.entries(formData)) {
36
+ if (val.trim() === "") continue; // or might throw an error
37
+ const num = Number(val);
38
+ payload[key] = isNaN(num) ? val : num;
39
+ }
40
+
41
+ setSubmitting(true);
42
+ setError("");
43
+
44
+ try {
45
+ const res = await fetch(`/api/team/${selectedTeam}/checkpoint`, {
46
+ method: "POST",
47
+ headers: { "Content-Type": "application/json" },
48
+ body: JSON.stringify(payload),
49
+ });
50
+
51
+ if (!res.ok) {
52
+ const data = await res.json();
53
+ throw new Error(data.error || "Failed to submit checkpoint data");
54
+ }
55
+
56
+ // Successfully submitted.
57
+ // The watcher plugin will reset the team status to "running"
58
+ // avoiding the need to manually close the modal.
59
+ } catch (err: any) {
60
+ setError(err.message || "Erro desconhecido ao submeter dados financeiros.");
61
+ } finally {
62
+ setSubmitting(false);
63
+ }
64
+ };
65
+
66
+ return (
67
+ <div style={{
68
+ position: "fixed",
69
+ top: 0, left: 0, right: 0, bottom: 0,
70
+ backgroundColor: "rgba(0, 0, 0, 0.7)",
71
+ display: "flex",
72
+ alignItems: "center",
73
+ justifyContent: "center",
74
+ zIndex: 9999,
75
+ backdropFilter: "blur(2px)"
76
+ }}>
77
+ <div style={{
78
+ backgroundColor: "var(--bg-main, #1e1e1e)",
79
+ borderRadius: 8,
80
+ width: 400,
81
+ maxWidth: "90%",
82
+ padding: 24,
83
+ boxShadow: "0 10px 25px rgba(0,0,0,0.5)",
84
+ border: "1px solid var(--border, #333)",
85
+ display: "flex",
86
+ flexDirection: "column",
87
+ gap: 16
88
+ }}>
89
+ <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
90
+ <h2 style={{ margin: 0, fontSize: 18, color: "var(--accent, #3b82f6)" }}>Atenção Necessária</h2>
91
+ </div>
92
+
93
+ <p style={{ margin: 0, fontSize: 13, color: "var(--text-muted, #ccc)" }}>
94
+ O agente encontrou dados faltantes (Halt & Catch protocol).
95
+ Por favor, preencha os valores abaixo para que o cálculo possa continuar com segurança.
96
+ </p>
97
+
98
+ <form onSubmit={handleSubmit} style={{ display: "flex", flexDirection: "column", gap: 12 }}>
99
+ {missingFields.map((field) => (
100
+ <div key={field}>
101
+ <label style={{ display: "block", fontSize: 12, marginBottom: 4, fontWeight: "bold" }}>
102
+ {field}
103
+ </label>
104
+ <input
105
+ type="text"
106
+ required
107
+ value={formData[field] || ""}
108
+ onChange={(e) => setFormData({ ...formData, [field]: e.target.value })}
109
+ style={{
110
+ width: "100%",
111
+ padding: "8px 12px",
112
+ borderRadius: 4,
113
+ border: "1px solid var(--border, #444)",
114
+ background: "var(--bg-sidebar, #121212)",
115
+ color: "inherit",
116
+ boxSizing: "border-box"
117
+ }}
118
+ />
119
+ </div>
120
+ ))}
121
+
122
+ {error && (
123
+ <div style={{ color: "#ef4444", fontSize: 13, background: "rgba(239,68,68,0.1)", padding: 8, borderRadius: 4, textAlign: "center" }}>
124
+ {error}
125
+ </div>
126
+ )}
127
+
128
+ <div style={{ display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 8 }}>
129
+ <button
130
+ type="submit"
131
+ disabled={submitting}
132
+ style={{
133
+ padding: "8px 16px",
134
+ background: "var(--accent, #3b82f6)",
135
+ border: "none",
136
+ color: "white",
137
+ borderRadius: 4,
138
+ cursor: submitting ? "not-allowed" : "pointer",
139
+ opacity: submitting ? 0.6 : 1,
140
+ fontWeight: 500
141
+ }}
142
+ >
143
+ {submitting ? "Enviando..." : "Enviar e Prosseguir"}
144
+ </button>
145
+ </div>
146
+ </form>
147
+ </div>
148
+ </div>
149
+ );
150
+ }
@@ -1,6 +1,6 @@
1
- import type { SquadStatus } from "@/types/state";
1
+ import type { TeamStatus } from "@/types/state";
2
2
 
3
- const STATUS_COLORS: Record<SquadStatus | "inactive", string> = {
3
+ const STATUS_COLORS: Record<TeamStatus | "inactive", string> = {
4
4
  idle: "#888",
5
5
  running: "var(--accent-cyan)",
6
6
  completed: "var(--accent-green)",
@@ -9,7 +9,7 @@ const STATUS_COLORS: Record<SquadStatus | "inactive", string> = {
9
9
  };
10
10
 
11
11
  interface StatusBadgeProps {
12
- status: SquadStatus | "inactive";
12
+ status: TeamStatus | "inactive";
13
13
  }
14
14
 
15
15
  export function StatusBadge({ status }: StatusBadgeProps) {
@@ -1,13 +1,13 @@
1
1
  import { useEffect, useState } from "react";
2
- import { useSquadStore } from "@/store/useSquadStore";
2
+ import { useTeamStore } from "@/store/useTeamStore";
3
3
  import { formatElapsed } from "@/lib/formatTime";
4
4
 
5
5
  export function StatusBar() {
6
- const selectedSquad = useSquadStore((s) => s.selectedSquad);
7
- const state = useSquadStore((s) =>
8
- s.selectedSquad ? s.activeStates.get(s.selectedSquad) : undefined
6
+ const selectedTeam = useTeamStore((s) => s.selectedTeam);
7
+ const state = useTeamStore((s) =>
8
+ s.selectedTeam ? s.activeStates.get(s.selectedTeam) : undefined
9
9
  );
10
- const isConnected = useSquadStore((s) => s.isConnected);
10
+ const isConnected = useTeamStore((s) => s.isConnected);
11
11
 
12
12
  // Elapsed timer
13
13
  const [elapsed, setElapsed] = useState(0);
@@ -25,11 +25,11 @@ export function StatusBar() {
25
25
  return () => clearInterval(interval);
26
26
  }, [state?.startedAt]);
27
27
 
28
- if (!selectedSquad || !state) {
28
+ if (!selectedTeam || !state) {
29
29
  return (
30
30
  <footer style={footerStyle}>
31
31
  <span style={{ color: "var(--text-secondary)" }}>
32
- Select an active squad to monitor
32
+ Select an active team to monitor
33
33
  </span>
34
34
  <ConnectionDot connected={isConnected} />
35
35
  </footer>
@@ -1,14 +1,14 @@
1
- import type { SquadInfo, SquadState } from "@/types/state";
1
+ import type { TeamInfo, TeamState } from "@/types/state";
2
2
  import { StatusBadge } from "./StatusBadge";
3
3
 
4
- interface SquadCardProps {
5
- squad: SquadInfo;
6
- state: SquadState | undefined;
4
+ interface TeamCardProps {
5
+ team: TeamInfo;
6
+ state: TeamState | undefined;
7
7
  isSelected: boolean;
8
8
  onSelect: () => void;
9
9
  }
10
10
 
11
- export function SquadCard({ squad, state, isSelected, onSelect }: SquadCardProps) {
11
+ export function TeamCard({ team, state, isSelected, onSelect }: TeamCardProps) {
12
12
  const isActive = !!state;
13
13
  const status = state?.status ?? "inactive";
14
14
 
@@ -33,9 +33,9 @@ export function SquadCard({ squad, state, isSelected, onSelect }: SquadCardProps
33
33
  }}
34
34
  >
35
35
  <StatusBadge status={status} />
36
- <span style={{ marginRight: 4 }}>{squad.icon}</span>
36
+ <span style={{ marginRight: 4 }}>{team.icon}</span>
37
37
  <span style={{ flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
38
- {squad.name}
38
+ {team.name}
39
39
  </span>
40
40
  {state?.step && (
41
41
  <span style={{ fontSize: 11, color: "var(--text-secondary)" }}>
@@ -1,14 +1,14 @@
1
- import { useSquadStore } from "@/store/useSquadStore";
2
- import { SquadCard } from "./SquadCard";
1
+ import { useTeamStore } from "@/store/useTeamStore";
2
+ import { TeamCard } from "./TeamCard";
3
3
 
4
- export function SquadSelector() {
5
- const squads = useSquadStore((s) => s.squads);
6
- const activeStates = useSquadStore((s) => s.activeStates);
7
- const selectedSquad = useSquadStore((s) => s.selectedSquad);
8
- const selectSquad = useSquadStore((s) => s.selectSquad);
4
+ export function TeamSelector() {
5
+ const teams = useTeamStore((s) => s.teams);
6
+ const activeStates = useTeamStore((s) => s.activeStates);
7
+ const selectedTeam = useTeamStore((s) => s.selectedTeam);
8
+ const selectTeam = useTeamStore((s) => s.selectTeam);
9
9
 
10
- // Sort: active squads first, then alphabetical
11
- const squadList = Array.from(squads.values()).sort((a, b) => {
10
+ // Sort: active teams first, then alphabetical
11
+ const teamList = Array.from(teams.values()).sort((a, b) => {
12
12
  const aActive = activeStates.has(a.code) ? 0 : 1;
13
13
  const bActive = activeStates.has(b.code) ? 0 : 1;
14
14
  if (aActive !== bActive) return aActive - bActive;
@@ -41,18 +41,18 @@ export function SquadSelector() {
41
41
  Squads
42
42
  </div>
43
43
  <div style={{ flex: 1, overflowY: "auto" }}>
44
- {squadList.length === 0 && (
44
+ {teamList.length === 0 && (
45
45
  <div style={{ padding: "16px 12px", color: "var(--text-secondary)", fontSize: 12 }}>
46
- No squads found
46
+ No teams found
47
47
  </div>
48
48
  )}
49
- {squadList.map((squad) => (
50
- <SquadCard
51
- key={squad.code}
52
- squad={squad}
53
- state={activeStates.get(squad.code)}
54
- isSelected={selectedSquad === squad.code}
55
- onSelect={() => selectSquad(squad.code)}
49
+ {teamList.map((team) => (
50
+ <TeamCard
51
+ key={team.code}
52
+ team={team}
53
+ state={activeStates.get(team.code)}
54
+ isSelected={selectedTeam === team.code}
55
+ onSelect={() => selectTeam(team.code)}
56
56
  />
57
57
  ))}
58
58
  </div>
@@ -1,5 +1,5 @@
1
1
  import { useEffect, useRef } from "react";
2
- import { useSquadStore } from "@/store/useSquadStore";
2
+ import { useTeamStore } from "@/store/useTeamStore";
3
3
  import type { WsMessage } from "@/types/state";
4
4
 
5
5
  const RECONNECT_BASE_MS = 1000;
@@ -7,14 +7,14 @@ const RECONNECT_MAX_MS = 30000;
7
7
  const WS_FAIL_THRESHOLD = 3;
8
8
  const POLL_INTERVAL_MS = 3000;
9
9
 
10
- export function useSquadSocket() {
10
+ export function useTeamSocket() {
11
11
  const wsRef = useRef<WebSocket | null>(null);
12
12
  const pollTimerRef = useRef<ReturnType<typeof setInterval> | null>(null);
13
13
 
14
- const setConnected = useSquadStore((s) => s.setConnected);
15
- const setSnapshot = useSquadStore((s) => s.setSnapshot);
16
- const updateSquadState = useSquadStore((s) => s.updateSquadState);
17
- const setSquadInactive = useSquadStore((s) => s.setSquadInactive);
14
+ const setConnected = useTeamStore((s) => s.setConnected);
15
+ const setSnapshot = useTeamStore((s) => s.setSnapshot);
16
+ const updateTeamState = useTeamStore((s) => s.updateTeamState);
17
+ const setTeamInactive = useTeamStore((s) => s.setTeamInactive);
18
18
 
19
19
  useEffect(() => {
20
20
  let disposed = false;
@@ -26,13 +26,13 @@ export function useSquadSocket() {
26
26
  if (disposed) return;
27
27
  switch (msg.type) {
28
28
  case "SNAPSHOT":
29
- setSnapshot(msg.squads, msg.activeStates);
29
+ setSnapshot(msg.teams, msg.activeStates);
30
30
  break;
31
- case "SQUAD_UPDATE":
32
- updateSquadState(msg.squad, msg.state);
31
+ case "TEAM_UPDATE":
32
+ updateTeamState(msg.team, msg.state);
33
33
  break;
34
- case "SQUAD_INACTIVE":
35
- setSquadInactive(msg.squad);
34
+ case "TEAM_INACTIVE":
35
+ setTeamInactive(msg.team);
36
36
  break;
37
37
  }
38
38
  }
@@ -78,7 +78,7 @@ export function useSquadSocket() {
78
78
 
79
79
  const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
80
80
  const ws = new WebSocket(
81
- `${protocol}//${window.location.host}/__squads_ws`,
81
+ `${protocol}//${window.location.host}/__teams_ws`,
82
82
  );
83
83
  wsRef.current = ws;
84
84
 
@@ -131,5 +131,5 @@ export function useSquadSocket() {
131
131
  wsRef.current?.close();
132
132
  wsRef.current = null;
133
133
  };
134
- }, [setConnected, setSnapshot, updateSquadState, setSquadInactive]);
134
+ }, [setConnected, setSnapshot, updateTeamState, setTeamInactive]);
135
135
  }
@@ -1,4 +1,4 @@
1
- import type { SquadState, Agent } from "@/types/state";
1
+ import type { TeamState, Agent } from "@/types/state";
2
2
 
3
3
  /**
4
4
  * Returns agents sorted by desk position (row first, then col).
@@ -13,13 +13,13 @@ export function sortAgentsByDesk(agents: Agent[]): Agent[] {
13
13
  /**
14
14
  * Find agent by id.
15
15
  */
16
- export function findAgent(state: SquadState, agentId: string): Agent | undefined {
16
+ export function findAgent(state: TeamState, agentId: string): Agent | undefined {
17
17
  return state.agents.find((a) => a.id === agentId);
18
18
  }
19
19
 
20
20
  /**
21
21
  * Returns the currently working agent, if any.
22
22
  */
23
- export function getWorkingAgent(state: SquadState): Agent | undefined {
23
+ export function getWorkingAgent(state: TeamState): Agent | undefined {
24
24
  return state.agents.find((a) => a.status === "working");
25
25
  }
@@ -8,7 +8,7 @@ import {
8
8
  import { CELL_W, CELL_H, MARGIN, WALL_H } from './palette';
9
9
  import { RoomBuilder } from './RoomBuilder';
10
10
  import { AgentSprite } from './AgentSprite';
11
- import type { SquadState, Agent } from '@/types/state';
11
+ import type { TeamState, Agent } from '@/types/state';
12
12
 
13
13
  function assignCharacters(agents: Agent[]): Map<string, CharacterName> {
14
14
  const assignments = new Map<string, CharacterName>();
@@ -80,14 +80,14 @@ export class OfficeScene extends Phaser.Scene {
80
80
 
81
81
  this.roomBuilder = new RoomBuilder(this);
82
82
 
83
- this.events.on('stateUpdate', (state: SquadState | null) => {
83
+ this.events.on('stateUpdate', (state: TeamState | null) => {
84
84
  this.onStateUpdate(state);
85
85
  });
86
86
 
87
87
  this.renderScene(DEMO_AGENTS);
88
88
  }
89
89
 
90
- private onStateUpdate(state: SquadState | null): void {
90
+ private onStateUpdate(state: TeamState | null): void {
91
91
  const agents = state?.agents ?? DEMO_AGENTS;
92
92
  this.renderScene(agents);
93
93
  }
@@ -1,7 +1,7 @@
1
1
  import { useEffect, useRef } from 'react';
2
2
  import Phaser from 'phaser';
3
3
  import { OfficeScene } from './OfficeScene';
4
- import { useSquadStore } from '@/store/useSquadStore';
4
+ import { useTeamStore } from '@/store/useTeamStore';
5
5
 
6
6
  export function PhaserGame() {
7
7
  const containerRef = useRef<HTMLDivElement>(null);
@@ -52,18 +52,18 @@ export function PhaserGame() {
52
52
 
53
53
  // Bridge React state → Phaser scene
54
54
  useEffect(() => {
55
- return useSquadStore.subscribe((state) => {
55
+ return useTeamStore.subscribe((state) => {
56
56
  const game = gameRef.current;
57
57
  if (!game) return;
58
58
  const scene = game.scene.getScene('OfficeScene') as OfficeScene | null;
59
59
  if (!scene || !scene.scene.isActive()) return;
60
60
 
61
- const selectedSquad = state.selectedSquad;
62
- const squadState = selectedSquad
63
- ? state.activeStates.get(selectedSquad) ?? null
61
+ const selectedTeam = state.selectedTeam;
62
+ const teamState = selectedTeam
63
+ ? state.activeStates.get(selectedTeam) ?? null
64
64
  : null;
65
65
 
66
- scene.events.emit('stateUpdate', squadState);
66
+ scene.events.emit('stateUpdate', teamState);
67
67
  });
68
68
  }, []);
69
69